refactor(code-actions): implement parameter object pattern for prompt generation

- Extract prompt templates into constants
- Add createPrompt utility for template string handling
- Consolidate code action handling in ClineProvider
- Update tests to use new parameter object pattern
This commit is contained in:
sam hoang
2025-01-12 21:20:02 +07:00
parent 02a8eb96f1
commit 1b26f91ea7
4 changed files with 79 additions and 40 deletions

View File

@@ -6,7 +6,10 @@ describe('Code Action Prompts', () => {
describe('explainCodePrompt', () => { describe('explainCodePrompt', () => {
it('should format explain prompt correctly', () => { it('should format explain prompt correctly', () => {
const prompt = explainCodePrompt(testFilePath, testCode); const prompt = explainCodePrompt({
filePath: testFilePath,
selectedText: testCode
});
expect(prompt).toContain(`@/${testFilePath}`); expect(prompt).toContain(`@/${testFilePath}`);
expect(prompt).toContain(testCode); expect(prompt).toContain(testCode);
@@ -18,7 +21,10 @@ describe('Code Action Prompts', () => {
describe('fixCodePrompt', () => { describe('fixCodePrompt', () => {
it('should format fix prompt without diagnostics', () => { it('should format fix prompt without diagnostics', () => {
const prompt = fixCodePrompt(testFilePath, testCode); const prompt = fixCodePrompt({
filePath: testFilePath,
selectedText: testCode
});
expect(prompt).toContain(`@/${testFilePath}`); expect(prompt).toContain(`@/${testFilePath}`);
expect(prompt).toContain(testCode); expect(prompt).toContain(testCode);
@@ -39,7 +45,11 @@ describe('Code Action Prompts', () => {
} }
]; ];
const prompt = fixCodePrompt(testFilePath, testCode, diagnostics); const prompt = fixCodePrompt({
filePath: testFilePath,
selectedText: testCode,
diagnostics
});
expect(prompt).toContain('Current problems detected:'); expect(prompt).toContain('Current problems detected:');
expect(prompt).toContain('[eslint] Missing semicolon (semi)'); expect(prompt).toContain('[eslint] Missing semicolon (semi)');
@@ -50,7 +60,10 @@ describe('Code Action Prompts', () => {
describe('improveCodePrompt', () => { describe('improveCodePrompt', () => {
it('should format improve prompt correctly', () => { it('should format improve prompt correctly', () => {
const prompt = improveCodePrompt(testFilePath, testCode); const prompt = improveCodePrompt({
filePath: testFilePath,
selectedText: testCode
});
expect(prompt).toContain(`@/${testFilePath}`); expect(prompt).toContain(`@/${testFilePath}`);
expect(prompt).toContain(testCode); expect(prompt).toContain(testCode);

View File

@@ -1,8 +1,29 @@
export const explainCodePrompt = (filePath: string, selectedText: string) => ` type PromptParams = Record<string, string | any[]>;
Explain the following code from file path @/${filePath}:
const generateDiagnosticText = (diagnostics?: any[]) => {
if (!diagnostics?.length) return '';
return `\nCurrent problems detected:\n${diagnostics.map(d =>
`- [${d.source || 'Error'}] ${d.message}${d.code ? ` (${d.code})` : ''}`
).join('\n')}`;
};
const createPrompt = (template: string, params: PromptParams): string => {
let result = template;
for (const [key, value] of Object.entries(params)) {
if (key === 'diagnostics') {
result = result.replaceAll('${diagnosticText}', generateDiagnosticText(value as any[]));
} else {
result = result.replaceAll(`\${${key}}`, value as string);
}
}
return result;
};
const EXPLAIN_TEMPLATE = `
Explain the following code from file path @/\${filePath}:
\`\`\` \`\`\`
${selectedText} \${selectedText}
\`\`\` \`\`\`
Please provide a clear and concise explanation of what this code does, including: Please provide a clear and concise explanation of what this code does, including:
@@ -11,18 +32,12 @@ Please provide a clear and concise explanation of what this code does, including
3. Important patterns or techniques used 3. Important patterns or techniques used
`; `;
export const fixCodePrompt = (filePath: string, selectedText: string, diagnostics?: any[]) => { const FIX_TEMPLATE = `
const diagnosticText = diagnostics && diagnostics.length > 0 Fix any issues in the following code from file path @/\${filePath}
? `\nCurrent problems detected: \${diagnosticText}
${diagnostics.map(d => `- [${d.source || 'Error'}] ${d.message}${d.code ? ` (${d.code})` : ''}`).join('\n')}`
: '';
return `
Fix any issues in the following code from file path @/${filePath}
${diagnosticText}
\`\`\` \`\`\`
${selectedText} \${selectedText}
\`\`\` \`\`\`
Please: Please:
@@ -31,13 +46,12 @@ Please:
3. Provide corrected code 3. Provide corrected code
4. Explain what was fixed and why 4. Explain what was fixed and why
`; `;
};
export const improveCodePrompt = (filePath: string, selectedText: string) => ` const IMPROVE_TEMPLATE = `
Improve the following code from file path @/${filePath}: Improve the following code from file path @/\${filePath}:
\`\`\` \`\`\`
${selectedText} \${selectedText}
\`\`\` \`\`\`
Please suggest improvements for: Please suggest improvements for:
@@ -48,3 +62,12 @@ Please suggest improvements for:
Provide the improved code along with explanations for each enhancement. Provide the improved code along with explanations for each enhancement.
`; `;
export const explainCodePrompt = (params: PromptParams) =>
createPrompt(EXPLAIN_TEMPLATE, params);
export const fixCodePrompt = (params: PromptParams) =>
createPrompt(FIX_TEMPLATE, params);
export const improveCodePrompt = (params: PromptParams) =>
createPrompt(IMPROVE_TEMPLATE, params);

View File

@@ -181,6 +181,20 @@ export class ClineProvider implements vscode.WebviewViewProvider {
return findLast(Array.from(this.activeInstances), (instance) => instance.view?.visible === true) return findLast(Array.from(this.activeInstances), (instance) => instance.view?.visible === true)
} }
public static async handleCodeAction(
promptGenerator: (params: Record<string, string | any[]>) => string,
params: Record<string, string | any[]>
): Promise<void> {
const visibleProvider = ClineProvider.getVisibleInstance()
if (!visibleProvider) {
return
}
const prompt = promptGenerator(params)
await visibleProvider.initClineWithTask(prompt)
}
resolveWebviewView( resolveWebviewView(
webviewView: vscode.WebviewView | vscode.WebviewPanel, webviewView: vscode.WebviewView | vscode.WebviewPanel,
//context: vscode.WebviewViewResolveContext<unknown>, used to recreate a deallocated webview, but we don't need this since we use retainContextWhenHidden //context: vscode.WebviewViewResolveContext<unknown>, used to recreate a deallocated webview, but we don't need this since we use retainContextWhenHidden

View File

@@ -174,34 +174,23 @@ export function activate(context: vscode.ExtensionContext) {
// Register code action commands // Register code action commands
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("roo-cline.explainCode", async (filePath: string, selectedText: string) => { vscode.commands.registerCommand("roo-cline.explainCode", async (filePath: string, selectedText: string) => {
const visibleProvider = ClineProvider.getVisibleInstance() await ClineProvider.handleCodeAction(explainCodePrompt, { filePath, selectedText })
if (!visibleProvider) {
return
}
const prompt = explainCodePrompt(filePath, selectedText)
await visibleProvider.initClineWithTask(prompt)
}) })
); );
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("roo-cline.fixCode", async (filePath: string, selectedText: string, diagnostics?: any[]) => { vscode.commands.registerCommand("roo-cline.fixCode", async (filePath: string, selectedText: string, diagnostics?: any[]) => {
const visibleProvider = ClineProvider.getVisibleInstance() await ClineProvider.handleCodeAction(fixCodePrompt, {
if (!visibleProvider) { filePath,
return selectedText,
} ...(diagnostics ? { diagnostics } : {})
const prompt = fixCodePrompt(filePath, selectedText, diagnostics) })
await visibleProvider.initClineWithTask(prompt)
}) })
); );
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("roo-cline.improveCode", async (filePath: string, selectedText: string) => { vscode.commands.registerCommand("roo-cline.improveCode", async (filePath: string, selectedText: string) => {
const visibleProvider = ClineProvider.getVisibleInstance() await ClineProvider.handleCodeAction(improveCodePrompt, { filePath, selectedText })
if (!visibleProvider) {
return
}
const prompt = improveCodePrompt(filePath, selectedText)
await visibleProvider.initClineWithTask(prompt)
}) })
); );