Skip to content

Commit 6d98f04

Browse files
committed
Merge branch 'feature/auto-debug' of https://github.com/MarcoWang3/aws-toolkit-vscode into feature/auto-debug
2 parents 301bb33 + e00b3b0 commit 6d98f04

32 files changed

+1590
-135
lines changed

buildspec/linuxTests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ phases:
4848
- VCS_COMMIT_ID="${CODEBUILD_RESOLVED_SOURCE_VERSION}"
4949
- CI_BUILD_URL=$(echo $CODEBUILD_BUILD_URL | sed 's/#/%23/g') # Encode `#` in the URL because otherwise the url is clipped in the Codecov.io site
5050
- CI_BUILD_ID="${CODEBUILD_BUILD_ID}"
51-
- test -n "${CODECOV_TOKEN}" && [ "$TARGET_BRANCH" = "master" ] && ./codecov --token=${CODECOV_TOKEN} --branch=${CODEBUILD_RESOLVED_SOURCE_VERSION} --repository=${CODEBUILD_SOURCE_REPO_URL} --file=./coverage/amazonq/lcov.info --file=./coverage/toolkit/lcov.info
51+
- test -n "${CODECOV_TOKEN}" && [ "$TARGET_BRANCH" = "master" ] && ./codecov --token=${CODECOV_TOKEN} --branch=${CODEBUILD_RESOLVED_SOURCE_VERSION} --repository=${CODEBUILD_SOURCE_REPO_URL} --file=./coverage/amazonq/lcov.info --file=./coverage/toolkit/lcov.info || true
5252

5353
reports:
5454
unit-test:

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.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "/transform: Show transformation history in Transformation Hub and allow users to resume jobs"
4+
}

packages/amazonq/package.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@
746746
},
747747
{
748748
"command": "aws.amazonq.showHistoryInHub",
749-
"title": "%AWS.command.q.transform.viewJobStatus%"
749+
"title": "%AWS.command.q.transform.viewJobHistory%"
750750
},
751751
{
752752
"command": "aws.amazonq.selectCustomization",
@@ -852,15 +852,21 @@
852852
},
853853
{
854854
"command": "aws.amazonq.inline.acceptEdit",
855-
"title": "%aws.amazonq.inline.acceptEdit%"
855+
"title": "%AWS.amazonq.inline.acceptEdit%",
856+
"category": "%AWS.amazonq.title%",
857+
"enablement": "aws.codewhisperer.connected"
856858
},
857859
{
858860
"command": "aws.amazonq.inline.rejectEdit",
859-
"title": "%aws.amazonq.inline.rejectEdit%"
861+
"title": "%AWS.amazonq.inline.rejectEdit%",
862+
"category": "%AWS.amazonq.title%",
863+
"enablement": "aws.codewhisperer.connected"
860864
},
861865
{
862866
"command": "aws.amazonq.toggleNextEditPredictionPanel",
863-
"title": "%aws.amazonq.toggleNextEditPredictionPanel%"
867+
"title": "%AWS.amazonq.toggleNextEditPredictionPanel%",
868+
"category": "%AWS.amazonq.title%",
869+
"enablement": "aws.codewhisperer.connected"
864870
}
865871
],
866872
"keybindings": [

packages/amazonq/src/app/inline/EditRendering/svgGenerator.ts

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { diffWordsWithSpace } from 'diff'
6+
import { diffWordsWithSpace, diffLines } from 'diff'
77
import * as vscode from 'vscode'
88
import { ToolkitError, getLogger } from 'aws-core-vscode/shared'
99
import { diffUtilities } from 'aws-core-vscode/shared'
@@ -42,10 +42,6 @@ export class SvgGenerationService {
4242
throw new ToolkitError('udiff format error')
4343
}
4444
const newCode = await diffUtilities.getPatchedCode(filePath, udiff)
45-
const modifiedLines = diffUtilities.getModifiedLinesFromUnifiedDiff(udiff)
46-
// TODO remove
47-
// eslint-disable-next-line aws-toolkits/no-json-stringify-in-log
48-
logger.info(`Line mapping: ${JSON.stringify(modifiedLines)}`)
4945

5046
const { createSVGWindow } = await import('svgdom')
5147

@@ -57,7 +53,12 @@ export class SvgGenerationService {
5753
const currentTheme = this.getEditorTheme()
5854

5955
// Get edit diffs with highlight
60-
const { addedLines, removedLines } = this.getEditedLinesFromDiff(udiff)
56+
const { addedLines, removedLines } = this.getEditedLinesFromCode(originalCode, newCode)
57+
58+
const modifiedLines = diffUtilities.getModifiedLinesFromCode(addedLines, removedLines)
59+
// TODO remove
60+
// eslint-disable-next-line aws-toolkits/no-json-stringify-in-log
61+
logger.info(`Line mapping: ${JSON.stringify(modifiedLines)}`)
6162

6263
// Calculate dimensions based on code content
6364
const { offset, editStartLine, isPositionValid } = this.calculatePosition(
@@ -175,43 +176,25 @@ export class SvgGenerationService {
175176
}
176177

177178
/**
178-
* Extract added and removed lines from the unified diff
179-
* @param unifiedDiff The unified diff string
179+
* Extract added and removed lines by comparing original and new code
180+
* @param originalCode The original code string
181+
* @param newCode The new code string
180182
* @returns Object containing arrays of added and removed lines
181183
*/
182-
private getEditedLinesFromDiff(unifiedDiff: string): { addedLines: string[]; removedLines: string[] } {
184+
private getEditedLinesFromCode(
185+
originalCode: string,
186+
newCode: string
187+
): { addedLines: string[]; removedLines: string[] } {
183188
const addedLines: string[] = []
184189
const removedLines: string[] = []
185-
const diffLines = unifiedDiff.split('\n')
186-
187-
// Find all hunks in the diff
188-
const hunkStarts = diffLines
189-
.map((line, index) => (line.startsWith('@@ ') ? index : -1))
190-
.filter((index) => index !== -1)
191190

192-
// Process each hunk to find added and removed lines
193-
for (const hunkStart of hunkStarts) {
194-
const hunkHeader = diffLines[hunkStart]
195-
const match = hunkHeader.match(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/)
191+
const changes = diffLines(originalCode, newCode)
196192

197-
if (!match) {
198-
continue
199-
}
200-
201-
// Extract the content lines for this hunk
202-
let i = hunkStart + 1
203-
while (i < diffLines.length && !diffLines[i].startsWith('@@')) {
204-
// Include lines that were added (start with '+')
205-
if (diffLines[i].startsWith('+') && !diffLines[i].startsWith('+++')) {
206-
const lineContent = diffLines[i].substring(1)
207-
addedLines.push(lineContent)
208-
}
209-
// Include lines that were removed (start with '-')
210-
else if (diffLines[i].startsWith('-') && !diffLines[i].startsWith('---')) {
211-
const lineContent = diffLines[i].substring(1)
212-
removedLines.push(lineContent)
213-
}
214-
i++
193+
for (const change of changes) {
194+
if (change.added) {
195+
addedLines.push(...change.value.split('\n').filter((line) => line.length > 0))
196+
} else if (change.removed) {
197+
removedLines.push(...change.value.split('\n').filter((line) => line.length > 0))
215198
}
216199
}
217200

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,16 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
290290
const prevSessionId = prevSession?.sessionId
291291
const prevItemId = this.sessionManager.getActiveRecommendation()?.[0]?.itemId
292292
const prevStartPosition = prevSession?.startPosition
293-
if (prevSession?.triggerOnAcceptance) {
293+
const editsTriggerOnAcceptance = prevSession?.triggerOnAcceptance
294+
if (editsTriggerOnAcceptance) {
294295
getAllRecommendationsOptions = {
295296
...getAllRecommendationsOptions,
296297
editsStreakToken: prevSession?.editsStreakPartialResultToken,
297298
}
298299
}
299300
const editor = window.activeTextEditor
300-
if (prevSession && prevSessionId && prevItemId && prevStartPosition) {
301+
// Skip prefix matching for Edits suggestions that trigger on acceptance.
302+
if (prevSession && prevSessionId && prevItemId && prevStartPosition && !editsTriggerOnAcceptance) {
301303
const prefix = document.getText(new Range(prevStartPosition, position))
302304
const prevItemMatchingPrefix = []
303305
for (const item of this.sessionManager.getActiveRecommendation()) {

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

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ import {
1212
import { CancellationToken, InlineCompletionContext, Position, TextDocument } from 'vscode'
1313
import { LanguageClient } from 'vscode-languageclient'
1414
import { SessionManager } from './sessionManager'
15-
import { AuthUtil, CodeWhispererStatusBarManager, vsCodeState } from 'aws-core-vscode/codewhisperer'
15+
import {
16+
AuthUtil,
17+
CodeWhispererConstants,
18+
CodeWhispererStatusBarManager,
19+
vsCodeState,
20+
} from 'aws-core-vscode/codewhisperer'
1621
import { TelemetryHelper } from './telemetryHelper'
1722
import { ICursorUpdateRecorder } from './cursorUpdateManager'
1823
import { getLogger } from 'aws-core-vscode/shared'
24+
import { getOpenFilesInWindow } from 'aws-core-vscode/utils'
25+
import { asyncCallWithTimeout } from '../../util/timeoutUtil'
1926

2027
export interface GetAllRecommendationsOptions {
2128
emitTelemetry?: boolean
@@ -35,6 +42,23 @@ export class RecommendationService {
3542
this.cursorUpdateRecorder = recorder
3643
}
3744

45+
async getRecommendationsWithTimeout(
46+
languageClient: LanguageClient,
47+
request: InlineCompletionWithReferencesParams,
48+
token: CancellationToken
49+
) {
50+
const resultPromise: Promise<InlineCompletionListWithReferences> = languageClient.sendRequest(
51+
inlineCompletionWithReferencesRequestType.method,
52+
request,
53+
token
54+
)
55+
return await asyncCallWithTimeout<InlineCompletionListWithReferences>(
56+
resultPromise,
57+
`${inlineCompletionWithReferencesRequestType.method} time out`,
58+
CodeWhispererConstants.promiseTimeoutLimit * 1000
59+
)
60+
}
61+
3862
async getAllRecommendations(
3963
languageClient: LanguageClient,
4064
document: TextDocument,
@@ -56,14 +80,15 @@ export class RecommendationService {
5680
contentChanges: documentChangeEvent.contentChanges.map((x) => x as TextDocumentContentChangeEvent),
5781
}
5882
: undefined
59-
83+
const openTabs = await getOpenFilesInWindow()
6084
let request: InlineCompletionWithReferencesParams = {
6185
textDocument: {
6286
uri: document.uri.toString(),
6387
},
6488
position,
6589
context,
6690
documentChangeParams: documentChangeParams,
91+
openTabFilepaths: openTabs,
6792
}
6893
if (options.editsStreakToken) {
6994
request = { ...request, partialResultToken: options.editsStreakToken }
@@ -93,11 +118,9 @@ export class RecommendationService {
93118
},
94119
})
95120
const t0 = performance.now()
96-
const result: InlineCompletionListWithReferences = await languageClient.sendRequest(
97-
inlineCompletionWithReferencesRequestType.method,
98-
request,
99-
token
100-
)
121+
122+
const result = await this.getRecommendationsWithTimeout(languageClient, request, token)
123+
101124
getLogger().info('Received inline completion response from LSP: %O', {
102125
sessionId: result.sessionId,
103126
latency: performance.now() - t0,
@@ -181,11 +204,7 @@ export class RecommendationService {
181204
while (nextToken) {
182205
const request = { ...initialRequest, partialResultToken: nextToken }
183206

184-
const result: InlineCompletionListWithReferences = await languageClient.sendRequest(
185-
inlineCompletionWithReferencesRequestType.method,
186-
request,
187-
token
188-
)
207+
const result = await this.getRecommendationsWithTimeout(languageClient, request, token)
189208
// when pagination is in progress, but user has already accepted or rejected an inline completion
190209
// then stop pagination
191210
if (this.sessionManager.getActiveSession() === undefined || vsCodeState.isCodeWhispererEditing) {

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
@@ -182,6 +182,8 @@ export async function startLanguageServer(
182182
modelSelection: true,
183183
workspaceFilePath: vscode.workspace.workspaceFile?.fsPath,
184184
codeReviewInChat: codeReviewInChat,
185+
// feature flag for displaying findings found not through CodeReview in the Code Issues Panel
186+
displayFindings: true,
185187
},
186188
window: {
187189
notifications: true,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export function asyncCallWithTimeout<T>(asyncPromise: Promise<T>, message: string, timeLimit: number): Promise<T> {
7+
let timeoutHandle: NodeJS.Timeout
8+
const timeoutPromise = new Promise((_resolve, reject) => {
9+
timeoutHandle = setTimeout(() => reject(new Error(message)), timeLimit)
10+
})
11+
return Promise.race([asyncPromise, timeoutPromise]).then((result) => {
12+
clearTimeout(timeoutHandle)
13+
return result as T
14+
})
15+
}

0 commit comments

Comments
 (0)