Skip to content

Commit 3af49b5

Browse files
authored
Merge branch 'aws:master' into master
2 parents 8fe741e + c9d6f91 commit 3af49b5

File tree

14 files changed

+387
-27
lines changed

14 files changed

+387
-27
lines changed

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/amazonq/src/app/inline/recommendationService.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import { TelemetryHelper } from './telemetryHelper'
2222
import { ICursorUpdateRecorder } from './cursorUpdateManager'
2323
import { getLogger } from 'aws-core-vscode/shared'
24+
import { getOpenFilesInWindow } from 'aws-core-vscode/utils'
2425
import { asyncCallWithTimeout } from '../../util/timeoutUtil'
2526

2627
export interface GetAllRecommendationsOptions {
@@ -79,14 +80,15 @@ export class RecommendationService {
7980
contentChanges: documentChangeEvent.contentChanges.map((x) => x as TextDocumentContentChangeEvent),
8081
}
8182
: undefined
82-
83+
const openTabs = await getOpenFilesInWindow()
8384
let request: InlineCompletionWithReferencesParams = {
8485
textDocument: {
8586
uri: document.uri.toString(),
8687
},
8788
position,
8889
context,
8990
documentChangeParams: documentChangeParams,
91+
openTabFilepaths: openTabs,
9092
}
9193
if (options.editsStreakToken) {
9294
request = { ...request, partialResultToken: options.editsStreakToken }

packages/amazonq/src/lsp/chat/messages.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,11 @@ async function handlePartialResult<T extends ChatResult>(
732732
// This is to filter out the message containing findings from CodeReview tool to update CodeIssues panel
733733
decryptedMessage.additionalMessages = decryptedMessage.additionalMessages?.filter(
734734
(message) =>
735-
!(message.messageId !== undefined && message.messageId.endsWith(CodeWhispererConstants.findingsSuffix))
735+
!(
736+
message.messageId !== undefined &&
737+
(message.messageId.endsWith(CodeWhispererConstants.codeReviewFindingsSuffix) ||
738+
message.messageId.endsWith(CodeWhispererConstants.displayFindingsSuffix))
739+
)
736740
)
737741

738742
if (decryptedMessage.body !== undefined) {
@@ -784,7 +788,11 @@ async function handleSecurityFindings(
784788
}
785789
for (let i = decryptedMessage.additionalMessages.length - 1; i >= 0; i--) {
786790
const message = decryptedMessage.additionalMessages[i]
787-
if (message.messageId !== undefined && message.messageId.endsWith(CodeWhispererConstants.findingsSuffix)) {
791+
if (
792+
message.messageId !== undefined &&
793+
(message.messageId.endsWith(CodeWhispererConstants.codeReviewFindingsSuffix) ||
794+
message.messageId.endsWith(CodeWhispererConstants.displayFindingsSuffix))
795+
) {
788796
if (message.body !== undefined) {
789797
try {
790798
const aggregatedCodeScanIssues: AggregatedCodeScanIssue[] = JSON.parse(message.body)
@@ -803,7 +811,12 @@ async function handleSecurityFindings(
803811
issue.visible = !isIssueTitleIgnored && !isSingleIssueIgnored
804812
}
805813
}
806-
initSecurityScanRender(aggregatedCodeScanIssues, undefined, CodeAnalysisScope.PROJECT)
814+
initSecurityScanRender(
815+
aggregatedCodeScanIssues,
816+
undefined,
817+
CodeAnalysisScope.AGENTIC,
818+
message.messageId.endsWith(CodeWhispererConstants.codeReviewFindingsSuffix)
819+
)
807820
SecurityIssueTreeViewProvider.focus()
808821
} catch (e) {
809822
languageClient.info('Failed to parse findings')

packages/amazonq/src/lsp/client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ export async function startLanguageServer(
183183
modelSelection: true,
184184
workspaceFilePath: vscode.workspace.workspaceFile?.fsPath,
185185
codeReviewInChat: codeReviewInChat,
186+
// feature flag for displaying findings found not through CodeReview in the Code Issues Panel
187+
displayFindings: true,
186188
},
187189
window: {
188190
notifications: true,

packages/amazonq/test/unit/amazonq/apps/inline/recommendationService.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ describe('RecommendationService', () => {
147147
position: mockPosition,
148148
context: mockContext,
149149
documentChangeParams: undefined,
150+
openTabFilepaths: [],
150151
})
151152

152153
// Verify session management
@@ -189,6 +190,7 @@ describe('RecommendationService', () => {
189190
position: mockPosition,
190191
context: mockContext,
191192
documentChangeParams: undefined,
193+
openTabFilepaths: [],
192194
}
193195
const secondRequestArgs = sendRequestStub.secondCall.args[1]
194196
assert.deepStrictEqual(firstRequestArgs, expectedRequestArgs)

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@
471471
"@aws-sdk/types": "^3.13.1",
472472
"@aws/chat-client": "^0.1.4",
473473
"@aws/chat-client-ui-types": "^0.1.47",
474-
"@aws/language-server-runtimes": "^0.2.111",
474+
"@aws/language-server-runtimes": "^0.2.119",
475475
"@aws/language-server-runtimes-types": "^0.1.47",
476476
"@cspotcode/source-map-support": "^0.8.1",
477477
"@sinonjs/fake-timers": "^10.0.2",

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ export async function startSecurityScan(
108108
zipUtil: ZipUtil = new ZipUtil(),
109109
scanUuid?: string
110110
) {
111+
if (scope === CodeAnalysisScope.AGENTIC) {
112+
throw new CreateCodeScanFailedError('Cannot use Agentic scope')
113+
}
111114
const profile = AuthUtil.instance.regionProfileManager.activeRegionProfile
112115
const logger = getLoggerForScope(scope)
113116
/**

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ export enum CodeAnalysisScope {
841841
FILE_AUTO = 'FILE_AUTO',
842842
FILE_ON_DEMAND = 'FILE_ON_DEMAND',
843843
PROJECT = 'PROJECT',
844+
AGENTIC = 'AGENTIC',
844845
}
845846

846847
export enum TestGenerationJobStatus {
@@ -907,4 +908,7 @@ export const predictionTrackerDefaultConfig = {
907908
maxSupplementalContext: 15,
908909
}
909910

910-
export const findingsSuffix = '_codeReviewFindings'
911+
export const codeReviewFindingsSuffix = '_codeReviewFindings'
912+
export const displayFindingsSuffix = '_displayFindings'
913+
914+
export const displayFindingsDetectorName = 'DisplayFindings'

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ export const securityScanRender: SecurityScanRender = {
2626
export function initSecurityScanRender(
2727
securityRecommendationList: AggregatedCodeScanIssue[],
2828
editor: vscode.TextEditor | undefined,
29-
scope: CodeAnalysisScope
29+
scope: CodeAnalysisScope,
30+
fromQCA: boolean = true
3031
) {
32+
// fromQCA parameter is used to determine if the findings are coming from QCA or from displayFindings tool.
33+
// if the incoming findings are from QCA review, then keep only existing findings from displayFindings
34+
// if the incoming findings are not from QCA review, then keep only the existing QCA findings
35+
securityScanRender.securityDiagnosticCollection = createSecurityDiagnosticCollection()
3136
securityScanRender.initialized = false
3237
if (scope === CodeAnalysisScope.FILE_ON_DEMAND && editor) {
3338
securityScanRender.securityDiagnosticCollection?.delete(editor.document.uri)
@@ -36,22 +41,20 @@ export function initSecurityScanRender(
3641
}
3742
for (const securityRecommendation of securityRecommendationList) {
3843
updateSecurityDiagnosticCollection(securityRecommendation)
39-
updateSecurityIssuesForProviders(securityRecommendation, scope === CodeAnalysisScope.FILE_AUTO)
44+
updateSecurityIssuesForProviders(securityRecommendation, scope === CodeAnalysisScope.FILE_AUTO, fromQCA)
4045
}
4146
securityScanRender.initialized = true
4247
}
4348

44-
function updateSecurityIssuesForProviders(securityRecommendation: AggregatedCodeScanIssue, isAutoScope?: boolean) {
49+
function updateSecurityIssuesForProviders(
50+
securityRecommendation: AggregatedCodeScanIssue,
51+
isAutoScope?: boolean,
52+
fromQCA: boolean = true
53+
) {
4554
if (isAutoScope) {
4655
SecurityIssueProvider.instance.mergeIssues(securityRecommendation)
4756
} else {
48-
const updatedSecurityRecommendationList = [
49-
...SecurityIssueProvider.instance.issues.filter(
50-
(group) => group.filePath !== securityRecommendation.filePath
51-
),
52-
securityRecommendation,
53-
]
54-
SecurityIssueProvider.instance.issues = updatedSecurityRecommendationList
57+
SecurityIssueProvider.instance.mergeIssuesDisplayFindings(securityRecommendation, fromQCA)
5558
}
5659
SecurityIssueTreeViewProvider.instance.refresh()
5760
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as vscode from 'vscode'
77
import { AggregatedCodeScanIssue, CodeScanIssue, SuggestedFix } from '../models/model'
88
import { randomUUID } from '../../shared/crypto'
9+
import { displayFindingsDetectorName } from '../models/constants'
910

1011
export class SecurityIssueProvider {
1112
static #instance: SecurityIssueProvider
@@ -161,6 +162,30 @@ export class SecurityIssueProvider {
161162
)
162163
}
163164

165+
public mergeIssuesDisplayFindings(newIssues: AggregatedCodeScanIssue, fromQCA: boolean) {
166+
const existingGroup = this._issues.find((group) => group.filePath === newIssues.filePath)
167+
if (!existingGroup) {
168+
this._issues.push(newIssues)
169+
return
170+
}
171+
172+
this._issues = this._issues.map((group) =>
173+
group.filePath !== newIssues.filePath
174+
? group
175+
: {
176+
...group,
177+
issues: [
178+
...group.issues.filter(
179+
// if the incoming findings are from QCA review, then keep only existing findings from displayFindings
180+
// if the incoming findings are not from QCA review, then keep only the existing QCA findings
181+
(issue) => fromQCA === (issue.detectorName === displayFindingsDetectorName)
182+
),
183+
...newIssues.issues,
184+
],
185+
}
186+
)
187+
}
188+
164189
private isExistingIssue(issue: CodeScanIssue, filePath: string) {
165190
return this._issues
166191
.find((group) => group.filePath === filePath)

0 commit comments

Comments
 (0)