Skip to content

Commit f41e85e

Browse files
committed
Quick fix actions
1 parent 8b072ad commit f41e85e

File tree

8 files changed

+116
-227
lines changed

8 files changed

+116
-227
lines changed

src/activate/handleTask.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
import * as vscode from "vscode"
2+
23
import { COMMAND_IDS } from "../core/CodeActionProvider"
34
import { ClineProvider } from "../core/webview/ClineProvider"
45
import { t } from "../i18n"
56

67
export const handleNewTask = async (params: { prompt?: string } | null | undefined) => {
78
let prompt = params?.prompt
9+
810
if (!prompt) {
911
prompt = await vscode.window.showInputBox({
1012
prompt: t("common:input.task_prompt"),
1113
placeHolder: t("common:input.task_placeholder"),
1214
})
1315
}
16+
1417
if (!prompt) {
1518
await vscode.commands.executeCommand("roo-cline.SidebarProvider.focus")
1619
return
1720
}
1821

19-
await ClineProvider.handleCodeAction(COMMAND_IDS.NEW_TASK, "NEW_TASK", {
20-
userInput: prompt,
21-
})
22+
await ClineProvider.handleCodeAction(COMMAND_IDS.NEW_TASK, "NEW_TASK", { userInput: prompt })
2223
}

src/activate/registerCodeActions.ts

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,19 @@ import { EditorUtils } from "../core/EditorUtils"
55
import { ClineProvider } from "../core/webview/ClineProvider"
66

77
export const registerCodeActions = (context: vscode.ExtensionContext) => {
8-
registerCodeActionPair(
9-
context,
10-
COMMAND_IDS.EXPLAIN,
11-
"EXPLAIN",
12-
"What would you like Roo to explain?",
13-
"E.g. How does the error handling work?",
14-
)
15-
16-
registerCodeActionPair(
17-
context,
18-
COMMAND_IDS.FIX,
19-
"FIX",
20-
"What would you like Roo to fix?",
21-
"E.g. Maintain backward compatibility",
22-
)
23-
24-
registerCodeActionPair(
25-
context,
26-
COMMAND_IDS.IMPROVE,
27-
"IMPROVE",
28-
"What would you like Roo to improve?",
29-
"E.g. Focus on performance optimization",
30-
)
31-
8+
registerCodeAction(context, COMMAND_IDS.FIX, "FIX")
329
registerCodeAction(context, COMMAND_IDS.ADD_TO_CONTEXT, "ADD_TO_CONTEXT")
3310
}
3411

3512
const registerCodeAction = (
3613
context: vscode.ExtensionContext,
3714
command: string,
3815
promptType: keyof typeof ACTION_NAMES,
39-
inputPrompt?: string,
40-
inputPlaceholder?: string,
4116
) => {
4217
let userInput: string | undefined
4318

4419
context.subscriptions.push(
4520
vscode.commands.registerCommand(command, async (...args: any[]) => {
46-
if (inputPrompt) {
47-
userInput = await vscode.window.showInputBox({
48-
prompt: inputPrompt,
49-
placeHolder: inputPlaceholder,
50-
})
51-
}
52-
5321
// Handle both code action and direct command cases.
5422
let filePath: string
5523
let selectedText: string
@@ -79,17 +47,3 @@ const registerCodeAction = (
7947
}),
8048
)
8149
}
82-
83-
const registerCodeActionPair = (
84-
context: vscode.ExtensionContext,
85-
baseCommand: string,
86-
promptType: keyof typeof ACTION_NAMES,
87-
inputPrompt?: string,
88-
inputPlaceholder?: string,
89-
) => {
90-
// Register new task version.
91-
registerCodeAction(context, baseCommand, promptType, inputPrompt, inputPlaceholder)
92-
93-
// Register current task version.
94-
registerCodeAction(context, `${baseCommand}InCurrentTask`, promptType, inputPrompt, inputPlaceholder)
95-
}

src/activate/registerCommands.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,51 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
6666
"roo-cline.activationCompleted": () => {},
6767
"roo-cline.plusButtonClicked": async () => {
6868
const visibleProvider = getVisibleProviderOrLog(outputChannel)
69-
if (!visibleProvider) return
69+
70+
if (!visibleProvider) {
71+
return
72+
}
73+
7074
await visibleProvider.removeClineFromStack()
7175
await visibleProvider.postStateToWebview()
7276
await visibleProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
7377
},
7478
"roo-cline.mcpButtonClicked": () => {
7579
const visibleProvider = getVisibleProviderOrLog(outputChannel)
76-
if (!visibleProvider) return
80+
81+
if (!visibleProvider) {
82+
return
83+
}
84+
7785
visibleProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })
7886
},
7987
"roo-cline.promptsButtonClicked": () => {
8088
const visibleProvider = getVisibleProviderOrLog(outputChannel)
81-
if (!visibleProvider) return
89+
90+
if (!visibleProvider) {
91+
return
92+
}
93+
8294
visibleProvider.postMessageToWebview({ type: "action", action: "promptsButtonClicked" })
8395
},
8496
"roo-cline.popoutButtonClicked": () => openClineInNewTab({ context, outputChannel }),
8597
"roo-cline.openInNewTab": () => openClineInNewTab({ context, outputChannel }),
8698
"roo-cline.settingsButtonClicked": () => {
8799
const visibleProvider = getVisibleProviderOrLog(outputChannel)
88-
if (!visibleProvider) return
100+
101+
if (!visibleProvider) {
102+
return
103+
}
104+
89105
visibleProvider.postMessageToWebview({ type: "action", action: "settingsButtonClicked" })
90106
},
91107
"roo-cline.historyButtonClicked": () => {
92108
const visibleProvider = getVisibleProviderOrLog(outputChannel)
93-
if (!visibleProvider) return
109+
110+
if (!visibleProvider) {
111+
return
112+
}
113+
94114
visibleProvider.postMessageToWebview({ type: "action", action: "historyButtonClicked" })
95115
},
96116
"roo-cline.helpButtonClicked": () => {
@@ -118,6 +138,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
118138
"roo-cline.focusInput": async () => {
119139
try {
120140
const panel = getPanel()
141+
121142
if (!panel) {
122143
await vscode.commands.executeCommand("workbench.view.extension.roo-cline-ActivityBar")
123144
} else if (panel === tabPanel) {
@@ -132,7 +153,11 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
132153
},
133154
"roo.acceptInput": () => {
134155
const visibleProvider = getVisibleProviderOrLog(outputChannel)
135-
if (!visibleProvider) return
156+
157+
if (!visibleProvider) {
158+
return
159+
}
160+
136161
visibleProvider.postMessageToWebview({ type: "acceptInput" })
137162
},
138163
}

src/core/CodeActionProvider.ts

Lines changed: 11 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import * as vscode from "vscode"
2+
23
import { EditorUtils } from "./EditorUtils"
34

4-
export const ACTION_NAMES = {
5-
EXPLAIN: "Roo Code: Explain Code",
6-
FIX: "Roo Code: Fix Code",
7-
FIX_LOGIC: "Roo Code: Fix Logic",
8-
IMPROVE: "Roo Code: Improve Code",
9-
ADD_TO_CONTEXT: "Roo Code: Add to Context",
10-
NEW_TASK: "Roo Code: New Task",
5+
type CodeActionName = "FIX" | "ADD_TO_CONTEXT" | "NEW_TASK"
6+
7+
export const ACTION_NAMES: Record<CodeActionName, string> = {
8+
FIX: "Fix in Roo Code",
9+
ADD_TO_CONTEXT: "Add to Roo Code",
10+
NEW_TASK: "New Roo Code Task",
1111
} as const
1212

13-
export const COMMAND_IDS = {
14-
EXPLAIN: "roo-cline.explainCode",
13+
export const COMMAND_IDS: Record<CodeActionName, string> = {
1514
FIX: "roo-cline.fixCode",
16-
IMPROVE: "roo-cline.improveCode",
1715
ADD_TO_CONTEXT: "roo-cline.addToContext",
1816
NEW_TASK: "roo-cline.newTask",
1917
} as const
@@ -30,25 +28,14 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
3028
return action
3129
}
3230

33-
private createActionPair(
34-
baseTitle: string,
35-
kind: vscode.CodeActionKind,
36-
baseCommand: string,
37-
args: any[],
38-
): vscode.CodeAction[] {
39-
return [
40-
this.createAction(`${baseTitle} in New Task`, kind, baseCommand, args),
41-
this.createAction(`${baseTitle} in Current Task`, kind, `${baseCommand}InCurrentTask`, args),
42-
]
43-
}
44-
4531
public provideCodeActions(
4632
document: vscode.TextDocument,
4733
range: vscode.Range | vscode.Selection,
4834
context: vscode.CodeActionContext,
4935
): vscode.ProviderResult<(vscode.CodeAction | vscode.Command)[]> {
5036
try {
5137
const effectiveRange = EditorUtils.getEffectiveRange(document, range)
38+
5239
if (!effectiveRange) {
5340
return []
5441
}
@@ -70,57 +57,24 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
7057
),
7158
)
7259

73-
actions.push(
74-
...this.createActionPair(ACTION_NAMES.EXPLAIN, vscode.CodeActionKind.QuickFix, COMMAND_IDS.EXPLAIN, [
75-
filePath,
76-
effectiveRange.text,
77-
effectiveRange.range.start.line + 1,
78-
effectiveRange.range.end.line + 1,
79-
]),
80-
)
81-
8260
if (context.diagnostics.length > 0) {
8361
const relevantDiagnostics = context.diagnostics.filter((d) =>
8462
EditorUtils.hasIntersectingRange(effectiveRange.range, d.range),
8563
)
8664

8765
if (relevantDiagnostics.length > 0) {
88-
const diagnosticMessages = relevantDiagnostics.map(EditorUtils.createDiagnosticData)
8966
actions.push(
90-
...this.createActionPair(ACTION_NAMES.FIX, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
67+
this.createAction(ACTION_NAMES.FIX, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
9168
filePath,
9269
effectiveRange.text,
9370
effectiveRange.range.start.line + 1,
9471
effectiveRange.range.end.line + 1,
95-
diagnosticMessages,
72+
relevantDiagnostics.map(EditorUtils.createDiagnosticData),
9673
]),
9774
)
9875
}
99-
} else {
100-
actions.push(
101-
...this.createActionPair(ACTION_NAMES.FIX_LOGIC, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
102-
filePath,
103-
effectiveRange.text,
104-
effectiveRange.range.start.line + 1,
105-
effectiveRange.range.end.line + 1,
106-
]),
107-
)
10876
}
10977

110-
actions.push(
111-
...this.createActionPair(
112-
ACTION_NAMES.IMPROVE,
113-
vscode.CodeActionKind.RefactorRewrite,
114-
COMMAND_IDS.IMPROVE,
115-
[
116-
filePath,
117-
effectiveRange.text,
118-
effectiveRange.range.start.line + 1,
119-
effectiveRange.range.end.line + 1,
120-
],
121-
),
122-
)
123-
12478
return actions
12579
} catch (error) {
12680
console.error("Error providing code actions:", error)

src/core/__tests__/CodeActionProvider.test.ts

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import * as vscode from "vscode"
44

5-
import { CodeActionProvider, ACTION_NAMES } from "../CodeActionProvider"
65
import { EditorUtils } from "../EditorUtils"
76

7+
import { CodeActionProvider, ACTION_NAMES } from "../CodeActionProvider"
8+
89
// Mock VSCode API
910
jest.mock("vscode", () => ({
1011
CodeAction: jest.fn().mockImplementation((title, kind) => ({
@@ -77,34 +78,20 @@ describe("CodeActionProvider", () => {
7778
it("should provide explain, improve, fix logic, and add to context actions by default", () => {
7879
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext)
7980

80-
expect(actions).toHaveLength(7) // 2 explain + 2 fix logic + 2 improve + 1 add to context
81+
expect(actions).toHaveLength(1)
8182
expect((actions as any)[0].title).toBe(ACTION_NAMES.ADD_TO_CONTEXT)
82-
expect((actions as any)[1].title).toBe(`${ACTION_NAMES.EXPLAIN} in New Task`)
83-
expect((actions as any)[2].title).toBe(`${ACTION_NAMES.EXPLAIN} in Current Task`)
84-
expect((actions as any)[3].title).toBe(`${ACTION_NAMES.FIX_LOGIC} in New Task`)
85-
expect((actions as any)[4].title).toBe(`${ACTION_NAMES.FIX_LOGIC} in Current Task`)
86-
expect((actions as any)[5].title).toBe(`${ACTION_NAMES.IMPROVE} in New Task`)
87-
expect((actions as any)[6].title).toBe(`${ACTION_NAMES.IMPROVE} in Current Task`)
8883
})
8984

9085
it("should provide fix action instead of fix logic when diagnostics exist", () => {
9186
mockContext.diagnostics = [
92-
{
93-
message: "test error",
94-
severity: vscode.DiagnosticSeverity.Error,
95-
range: mockRange,
96-
},
87+
{ message: "test error", severity: vscode.DiagnosticSeverity.Error, range: mockRange },
9788
]
9889

9990
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext)
10091

101-
expect(actions).toHaveLength(7) // 2 explain + 2 fix + 2 improve + 1 add to context
102-
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX} in New Task`)).toBe(true)
103-
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX} in Current Task`)).toBe(true)
104-
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX_LOGIC} in New Task`)).toBe(false)
105-
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX_LOGIC} in Current Task`)).toBe(
106-
false,
107-
)
92+
expect(actions).toHaveLength(2)
93+
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX}`)).toBe(true)
94+
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.ADD_TO_CONTEXT}`)).toBe(true)
10895
})
10996

11097
it("should return empty array when no effective range", () => {

src/core/webview/ClineProvider.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,17 +279,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
279279
const prompt = supportPrompt.create(promptType, params, customSupportPrompts)
280280

281281
if (command.endsWith("addToContext")) {
282-
await visibleProvider.postMessageToWebview({
283-
type: "invoke",
284-
invoke: "setChatBoxMessage",
285-
text: prompt,
286-
})
287-
288-
return
289-
}
290-
291-
if (visibleProvider.getCurrentCline() && command.endsWith("InCurrentTask")) {
292-
await visibleProvider.postMessageToWebview({ type: "invoke", invoke: "sendMessage", text: prompt })
282+
await visibleProvider.postMessageToWebview({ type: "invoke", invoke: "setChatBoxMessage", text: prompt })
293283
return
294284
}
295285

0 commit comments

Comments
 (0)