Skip to content

Commit cf5767f

Browse files
committed
On Demand Fix Scans
1 parent 5eea5f9 commit cf5767f

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

packages/core/src/codewhisperer/activation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
notifyNewCustomizationsCmd,
3939
connectWithCustomization,
4040
applySecurityFix,
41+
generateSecurityFix,
4142
signoutCodeWhisperer,
4243
toggleCodeScans,
4344
registerToolkitApiCallback,
@@ -236,6 +237,8 @@ export async function activate(context: ExtContext): Promise<void> {
236237
refreshStatusBar.register(),
237238
// apply suggested fix
238239
applySecurityFix.register(),
240+
// generate fix using Amazon Q
241+
generateSecurityFix.register(),
239242
// quick pick with codewhisperer options
240243
listCodeWhispererCommands.register(),
241244
// manual trigger

packages/core/src/codewhisperer/commands/basicCommands.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,137 @@ export const installAmazonQExtension = Commands.declare(
339339
focusQAfterDelay()
340340
}
341341
)
342+
/*
343+
TODO:
344+
Show the notification of generating fix while fix is getting generated from the backend.
345+
open a diff view of original code and changed code
346+
Give an option in the diff is possibe or given in showInformation box whether they want to accept the changed code ?
347+
If accepted the changed code then paste the code to the editor and close the opendiff and show the editor file with removing the yellow lines on the issue.
348+
If user discarded the generate fix Do nothing
349+
Add telemetry for every action.
350+
*/
351+
352+
export const generateSecurityFix = Commands.declare(
353+
'aws.amazonq.generateSecurityFix',
354+
() => async (issue: CodeScanIssue, filePath: string, source: Component) => {
355+
/* Working
356+
return vscode.window.withProgress(
357+
{
358+
location: vscode.ProgressLocation.Notification,
359+
// title: CodeWhispererConstants.runningSecurityScan,
360+
title: "Generating security fix...",
361+
cancellable: false,
362+
},
363+
async () => {
364+
const uri = vscode.Uri.file(filePath);
365+
366+
try {
367+
const originalDoc = await vscode.workspace.openTextDocument(uri);
368+
const originalCode = originalDoc.getText();
369+
370+
const originalTempUri = vscode.Uri.parse(`${uri.fsPath}`);
371+
const changedTempUri = vscode.Uri.parse(`untitled:changed_${uri.fsPath}`);
372+
373+
await vscode.workspace.openTextDocument(changedTempUri).then(async doc => {
374+
const edit = new vscode.WorkspaceEdit();
375+
edit.insert(changedTempUri, new vscode.Position(0, 0), originalCode.toUpperCase());
376+
const success = await vscode.workspace.applyEdit(edit)
377+
});
378+
await vscode.commands.executeCommand(
379+
'vscode.diff',
380+
originalTempUri,
381+
changedTempUri,
382+
`Diff: ${uri.fsPath}`
383+
);
384+
385+
} catch (error) {
386+
vscode.window.showErrorMessage(`Failed to show diff: ${error.message}`);
387+
}
388+
}
389+
)
390+
// void vscode.window.showInformationMessage(`Generating security fix...`)
391+
*/
392+
393+
return vscode.window.withProgress(
394+
{
395+
location: vscode.ProgressLocation.Notification,
396+
title: 'Generating security fix...',
397+
cancellable: false,
398+
},
399+
async () => {
400+
const uri = vscode.Uri.file(filePath)
401+
402+
try {
403+
const originalDoc = await vscode.workspace.openTextDocument(uri)
404+
const originalCode = originalDoc.getText()
405+
406+
const originalTempUri = vscode.Uri.parse(`${uri.fsPath}`)
407+
const changedTempUri = vscode.Uri.parse(`untitled:changed_${uri.fsPath}`)
408+
409+
await vscode.workspace.openTextDocument(changedTempUri).then(async (doc) => {
410+
const edit = new vscode.WorkspaceEdit()
411+
edit.insert(changedTempUri, new vscode.Position(0, 0), originalCode.toUpperCase())
412+
const success = await vscode.workspace.applyEdit(edit)
413+
})
414+
415+
const diffResult = await vscode.commands.executeCommand(
416+
'vscode.diff',
417+
originalTempUri,
418+
changedTempUri,
419+
`Diff: ${uri.fsPath}`
420+
)
421+
422+
// Prompt user to accept or ignore the changes
423+
const acceptChanges = 'Accept Changes'
424+
const ignoreChanges = 'Ignore Changes'
425+
426+
const userChoice = await vscode.window.showInformationMessage(
427+
'Do you want to accept the changes?',
428+
{ modal: true },
429+
acceptChanges,
430+
ignoreChanges
431+
)
432+
433+
if (userChoice === acceptChanges) {
434+
// Apply changes to the original document
435+
const edit = new vscode.WorkspaceEdit()
436+
edit.replace(
437+
uri,
438+
new vscode.Range(
439+
new vscode.Position(0, 0),
440+
originalDoc.lineAt(originalDoc.lineCount - 1).range.end
441+
),
442+
originalCode.toUpperCase()
443+
)
444+
const success = await vscode.workspace.applyEdit(edit)
445+
if (success) {
446+
await originalDoc.save()
447+
vscode.window.showInformationMessage('Changes applied successfully!')
448+
} else {
449+
vscode.window.showErrorMessage('Failed to apply changes.')
450+
}
451+
} else {
452+
vscode.window.showInformationMessage('Changes ignored.')
453+
}
454+
await vscode.commands.executeCommand('workbench.action.closeActiveEditor')
455+
const changedDoc = await vscode.workspace.openTextDocument(changedTempUri)
456+
const discardEdit = new vscode.WorkspaceEdit()
457+
discardEdit.replace(
458+
changedTempUri,
459+
new vscode.Range(
460+
new vscode.Position(0, 0),
461+
changedDoc.lineAt(changedDoc.lineCount - 1).range.end
462+
),
463+
''
464+
)
465+
await vscode.workspace.applyEdit(discardEdit)
466+
} catch (error) {
467+
vscode.window.showErrorMessage(`Failed to show diff: ${error.message}`)
468+
}
469+
}
470+
)
471+
}
472+
)
342473

343474
export const applySecurityFix = Commands.declare(
344475
'aws.amazonq.applySecurityFix',

packages/core/src/codewhisperer/service/securityIssueHoverProvider.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ export class SecurityIssueHoverProvider extends SecurityIssueProvider implements
103103
markdownString.appendMarkdown(
104104
`${this._makeCodeBlock(suggestedFix.code, issue.detectorId.split('/').shift())}\n`
105105
)
106+
} else {
107+
const generateFixCommand = this._getCommandMarkdown(
108+
'aws.amazonq.generateSecurityFix',
109+
[issue, filePath, 'hover'],
110+
'wrench',
111+
'Generate Fix',
112+
'Generate Fix with Amazon Q'
113+
)
114+
markdownString.appendMarkdown(' | ' + generateFixCommand)
106115
}
107116

108117
return markdownString

0 commit comments

Comments
 (0)