Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
0d4c188
feat(amazonq): parse message from agentic reviewer
blakelaz-amazon Jun 19, 2025
983a87d
feat(amazonq): support array of AggregatedCodeScanIssue objects from …
blakelaz-amazon Jun 20, 2025
51f72b0
fix(amazonq): change findings suffix to make it more precise
blakelaz-amazon Jun 20, 2025
694a48e
Merge PR #7535: Amazon Q security findings improvements
singhAws Jun 20, 2025
9e58c93
feat(amazonq): store the findings locally and include a path to them …
blakelaz-amazon Jun 21, 2025
3ece0a5
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 21, 2025
1f4cfc4
fix: update q code review finding message suffix
singhAws Jun 22, 2025
2fc9f36
fix(amazonq): change the findings suffix, adjust the stored findings …
blakelaz-amazon Jun 24, 2025
00a8a71
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 24, 2025
e6d2f06
feat(amazonq): improve explain with q option for code issue
blakelaz-amazon Jun 25, 2025
1e018a3
Merge pull request #1 from BlakeLazarine/master
Rathore25 Jun 25, 2025
865b0e3
feat(amazonq): update findings bar
blakelaz-amazon Jun 25, 2025
4c92e7f
Merge pull request #2 from BlakeLazarine/master
Rathore25 Jun 25, 2025
5b7df16
fix: remove unused code
singhAws Jun 25, 2025
fae3d78
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 25, 2025
b3a722c
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 26, 2025
98b1265
fix(amazonq): commenting out unncalled functions, unused imports
blakelaz-amazon Jun 27, 2025
c986e49
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 27, 2025
4d82ab5
Merge latest changes from origin/master into code-review-tool
singhAws Jul 1, 2025
794098a
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 2, 2025
daa3ffe
Updated explain code issue prompt
singhAws Jul 2, 2025
acaaf30
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 3, 2025
56a664d
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 3, 2025
3ed1c1a
Merge branch 'master' into code-review-tool
BlakeLazarine Jul 3, 2025
6a6e9b1
Merge pull request #1 from Rathore25/code-review-tool
BlakeLazarine Jul 3, 2025
784ae63
feat(amazonq): separate the Explain and Generate Fix commands
blakelaz-amazon Jul 3, 2025
3cf0343
Merge pull request #3 from BlakeLazarine/master
Rathore25 Jul 3, 2025
f46106b
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 3, 2025
ec7048e
fix: remove commented code
singhAws Jul 4, 2025
ccc19de
fix: update explain issue prompt
singhAws Jul 6, 2025
33da660
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 7, 2025
c19d712
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 8, 2025
11bcfc9
fix(amazonq): change 'Generate Fix' to 'Fix' and remove form code is…
blakelaz-amazon Jul 8, 2025
138cd00
Merge pull request #4 from BlakeLazarine/master
Rathore25 Jul 8, 2025
c0568d5
Merge latest changes from master into code-review-tool branch
singhAws Jul 8, 2025
f1b6936
fix: remove unnecessary imports
singhAws Jul 8, 2025
b4f2dec
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 8, 2025
a479a42
fix(amazonq): improve line numbering in Explain and Fix commands
blakelaz-amazon Jul 8, 2025
bf34866
Merge pull request #5 from BlakeLazarine/master
Rathore25 Jul 9, 2025
d512fac
fix: update explain and fix prompt
singhAws Jul 9, 2025
861902e
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 9, 2025
f16e25a
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 9, 2025
1707040
feat(amazonq): add agentic reviewer feature flag
blakelaz-amazon Jul 9, 2025
700f206
Merge pull request #6 from BlakeLazarine/master
BlakeLazarine Jul 9, 2025
b5ab217
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 10, 2025
2f80057
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 10, 2025
9d47e20
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 11, 2025
e50149e
fix: update qCodeReview tool enable flag to
singhAws Jul 11, 2025
1cd9433
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 11, 2025
fdb95b1
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 12, 2025
a2adea0
Merge branch 'aws:master' into code-review-tool
singhAws Jul 14, 2025
42223b9
Merge branch 'aws:master' into code-review-tool
singhAws Jul 14, 2025
076fbfd
Merge branch 'aws:master' into code-review-tool
singhAws Jul 14, 2025
81617eb
fix: fix unit tests
singhAws Jul 14, 2025
8e8c9e9
fix: remove tests for generateFix, as we are not generating fixes any…
singhAws Jul 14, 2025
a65e8e7
fix: removed unused imports
singhAws Jul 14, 2025
63b99ae
fix: fix duplicate code
singhAws Jul 14, 2025
d1ea87a
Merge branch 'aws:master' into code-review-tool
singhAws Jul 14, 2025
b7950e6
fix: fix unit tests
singhAws Jul 15, 2025
92a2d01
fix: update change log for CodeIssues related changes
singhAws Jul 15, 2025
94903b5
Merge branch 'aws:master' into code-review-tool
singhAws Jul 15, 2025
c9164a1
fix: addressed pr comments
singhAws Jul 15, 2025
f6183dc
fix: show and log error when error while open file with selection
singhAws Jul 15, 2025
534f875
fix: update change log
singhAws Jul 15, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "Explain and Fix for any issue in Code Issues panel will pull the experience into chat. Also no more view details tab."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
Feel free to ig

Amazon Q: Explain and Fix for any issue in Code Issues panel will pull the experience into chat. Also no more view details tab.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "QCodeReview tool will update CodeIssues panel along with quick action - `/review`"
}
17 changes: 12 additions & 5 deletions packages/amazonq/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,17 +442,22 @@
},
{
"command": "aws.amazonq.openSecurityIssuePanel",
"when": "false && view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@4"
},
{
"command": "aws.amazonq.security.explain",
"when": "view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@4"
},
{
"command": "aws.amazonq.security.ignore",
"command": "aws.amazonq.security.generateFix",
"when": "view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@5"
},
{
"command": "aws.amazonq.security.generateFix",
"when": "view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithoutFix",
"command": "aws.amazonq.security.ignore",
"when": "view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@6"
},
{
Expand Down Expand Up @@ -535,16 +540,17 @@
"aws.amazonq.submenu.securityIssueMoreActions": [
{
"command": "aws.amazonq.security.explain",
"when": "false",
"group": "1_more@1"
},
{
"command": "aws.amazonq.applySecurityFix",
"when": "view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"when": "false && view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"group": "1_more@3"
},
{
"command": "aws.amazonq.security.regenerateFix",
"when": "view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"when": "false && view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"group": "1_more@4"
},
{
Expand Down Expand Up @@ -793,6 +799,7 @@
{
"command": "aws.amazonq.security.explain",
"title": "%AWS.command.amazonq.explainIssue%",
"icon": "$(search)",
"enablement": "view == aws.amazonq.SecurityIssuesTree"
},
{
Expand Down
113 changes: 73 additions & 40 deletions packages/amazonq/src/lsp/chat/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { Commands, globals } from 'aws-core-vscode/shared'
import { window } from 'vscode'
import { AmazonQChatViewProvider } from './webviewProvider'
import { CodeScanIssue } from 'aws-core-vscode/codewhisperer'
import { EditorContextExtractor } from 'aws-core-vscode/codewhispererChat'
import { getLogger } from 'aws-core-vscode/shared'
import * as vscode from 'vscode'
import * as path from 'path'

/**
* TODO: Re-enable these once we can figure out which path they're going to live in
Expand All @@ -21,45 +23,24 @@ export function registerCommands(provider: AmazonQChatViewProvider) {
registerGenericCommand('aws.amazonq.optimizeCode', 'Optimize', provider),
registerGenericCommand('aws.amazonq.generateUnitTests', 'Generate Tests', provider),

Commands.register('aws.amazonq.explainIssue', async (issue: CodeScanIssue) => {
void focusAmazonQPanel().then(async () => {
const editorContextExtractor = new EditorContextExtractor()
const extractedContext = await editorContextExtractor.extractContextForTrigger('ContextMenu')
const selectedCode =
extractedContext?.activeFileContext?.fileText
?.split('\n')
.slice(issue.startLine, issue.endLine)
.join('\n') ?? ''

// The message that gets sent to the UI
const uiMessage = [
'Explain the ',
issue.title,
' issue in the following code:',
'\n```\n',
selectedCode,
'\n```',
].join('')

// The message that gets sent to the backend
const contextMessage = `Explain the issue "${issue.title}" (${JSON.stringify(
issue
)}) and generate code demonstrating the fix`

void provider.webview?.postMessage({
command: 'sendToPrompt',
params: {
selection: '',
triggerType: 'contextMenu',
prompt: {
prompt: uiMessage, // what gets sent to the user
escapedPrompt: contextMessage, // what gets sent to the backend
},
autoSubmit: true,
},
})
})
}),
Commands.register('aws.amazonq.explainIssue', (issue: CodeScanIssue, filePath: string) =>
handleIssueCommand(
issue,
filePath,
'Explain',
'Provide a small description of the issue. You must not attempt to fix the issue. You should only give a small summary of it to the user.',
provider
)
),
Commands.register('aws.amazonq.generateFix', (issue: CodeScanIssue, filePath: string) =>
handleIssueCommand(
issue,
filePath,
'Fix',
'Generate a fix for the following code issue. You must not explain the issue, just generate and explain the fix. The user should have the option to accept or reject the fix before any code is changed.',
provider
)
),
Commands.register('aws.amazonq.sendToPrompt', (data) => {
const triggerType = getCommandTriggerType(data)
const selection = getSelectedText()
Expand All @@ -85,6 +66,58 @@ export function registerCommands(provider: AmazonQChatViewProvider) {
)
}

async function handleIssueCommand(
issue: CodeScanIssue,
filePath: string,
action: string,
contextPrompt: string,
provider: AmazonQChatViewProvider
) {
await focusAmazonQPanel()

if (issue && filePath) {
await openFileWithSelection(issue, filePath)
}

const lineRange = createLineRangeText(issue)
const visibleMessageInChat = `_${action} **${issue.title}** issue in **${path.basename(filePath)}** at \`${lineRange}\`_`
const contextMessage = `${contextPrompt} Code issue - ${JSON.stringify(issue)}`

void provider.webview?.postMessage({
command: 'sendToPrompt',
params: {
selection: '',
triggerType: 'contextMenu',
prompt: {
prompt: visibleMessageInChat,
escapedPrompt: contextMessage,
},
autoSubmit: true,
},
})
}

async function openFileWithSelection(issue: CodeScanIssue, filePath: string) {
try {
const range = new vscode.Range(issue.startLine, 0, issue.endLine, 0)
const doc = await vscode.workspace.openTextDocument(filePath)
await vscode.window.showTextDocument(doc, {
selection: range,
viewColumn: vscode.ViewColumn.One,
preview: true,
})
} catch (e) {
getLogger().error('openFileWithSelection: Failed to open file %s with selection: %O', filePath, e)
void vscode.window.showInformationMessage('Failed to display file with issue.')
}
}

function createLineRangeText(issue: CodeScanIssue): string {
return issue.startLine === issue.endLine - 1
? `[${issue.startLine + 1}]`
: `[${issue.startLine + 1}, ${issue.endLine}]`
}

function getSelectedText(): string {
const editor = window.activeTextEditor
if (editor) {
Expand Down
63 changes: 58 additions & 5 deletions packages/amazonq/src/lsp/chat/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,16 @@ import { v4 as uuidv4 } from 'uuid'
import * as vscode from 'vscode'
import { Disposable, LanguageClient, Position, TextDocumentIdentifier } from 'vscode-languageclient'
import { AmazonQChatViewProvider } from './webviewProvider'
import { AuthUtil, ReferenceLogViewProvider } from 'aws-core-vscode/codewhisperer'
import {
AggregatedCodeScanIssue,
AuthUtil,
CodeAnalysisScope,
CodeWhispererSettings,
initSecurityScanRender,
ReferenceLogViewProvider,
SecurityIssueTreeViewProvider,
CodeWhispererConstants,
} from 'aws-core-vscode/codewhisperer'
import { amazonQDiffScheme, AmazonQPromptSettings, messages, openUrl, isTextEditor } from 'aws-core-vscode/shared'
import {
DefaultAmazonQAppInitContext,
Expand All @@ -85,6 +94,7 @@ import { isValidResponseError } from './error'
import { decryptResponse, encryptRequest } from '../encryption'
import { getCursorState } from '../utils'
import { focusAmazonQPanel } from './commands'
import { ChatMessage } from '@aws/language-server-runtimes/server-interface'

export function registerActiveEditorChangeListener(languageClient: LanguageClient) {
let debounceTimer: NodeJS.Timeout | undefined
Expand Down Expand Up @@ -299,7 +309,8 @@ export function registerMessageListeners(
encryptionKey,
provider,
chatParams.tabId,
chatDisposable
chatDisposable,
languageClient
)
} catch (e) {
const errorMsg = `Error occurred during chat request: ${e}`
Expand All @@ -315,7 +326,8 @@ export function registerMessageListeners(
encryptionKey,
provider,
chatParams.tabId,
chatDisposable
chatDisposable,
languageClient
)
} finally {
chatStreamTokens.delete(chatParams.tabId)
Expand Down Expand Up @@ -359,7 +371,8 @@ export function registerMessageListeners(
encryptionKey,
provider,
message.params.tabId,
quickActionDisposable
quickActionDisposable,
languageClient
)
break
}
Expand Down Expand Up @@ -612,6 +625,12 @@ async function handlePartialResult<T extends ChatResult>(
) {
const decryptedMessage = await decryptResponse<T>(partialResult, encryptionKey)

// This is to filter out the message containing findings from qCodeReview tool to update CodeIssues panel
decryptedMessage.additionalMessages = decryptedMessage.additionalMessages?.filter(
(message) =>
!(message.messageId !== undefined && message.messageId.endsWith(CodeWhispererConstants.findingsSuffix))
)

if (decryptedMessage.body !== undefined) {
void provider.webview?.postMessage({
command: chatRequestType.method,
Expand All @@ -632,10 +651,13 @@ async function handleCompleteResult<T extends ChatResult>(
encryptionKey: Buffer | undefined,
provider: AmazonQChatViewProvider,
tabId: string,
disposable: Disposable
disposable: Disposable,
languageClient: LanguageClient
) {
const decryptedMessage = await decryptResponse<T>(result, encryptionKey)

handleSecurityFindings(decryptedMessage, languageClient)

void provider.webview?.postMessage({
command: chatRequestType.method,
params: decryptedMessage,
Expand All @@ -649,6 +671,37 @@ async function handleCompleteResult<T extends ChatResult>(
disposable.dispose()
}

function handleSecurityFindings(
decryptedMessage: { additionalMessages?: ChatMessage[] },
languageClient: LanguageClient
): void {
if (decryptedMessage.additionalMessages === undefined || decryptedMessage.additionalMessages.length === 0) {
return
}
for (let i = decryptedMessage.additionalMessages.length - 1; i >= 0; i--) {
const message = decryptedMessage.additionalMessages[i]
if (message.messageId !== undefined && message.messageId.endsWith(CodeWhispererConstants.findingsSuffix)) {
if (message.body !== undefined) {
try {
const aggregatedCodeScanIssues: AggregatedCodeScanIssue[] = JSON.parse(message.body)
for (const aggregatedCodeScanIssue of aggregatedCodeScanIssues) {
for (const issue of aggregatedCodeScanIssue.issues) {
issue.visible = !CodeWhispererSettings.instance
.getIgnoredSecurityIssues()
.includes(issue.title)
}
}
initSecurityScanRender(aggregatedCodeScanIssues, undefined, CodeAnalysisScope.PROJECT)
SecurityIssueTreeViewProvider.focus()
} catch (e) {
languageClient.info('Failed to parse findings')
}
}
decryptedMessage.additionalMessages.splice(i, 1)
}
}
}

async function resolveChatResponse(
requestMethod: string,
params: any,
Expand Down
1 change: 1 addition & 0 deletions packages/amazonq/src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export async function startLanguageServer(
reroute: true,
modelSelection: true,
workspaceFilePath: vscode.workspace.workspaceFile?.fsPath,
qCodeReviewInChat: true,
},
window: {
notifications: true,
Expand Down
Loading
Loading