-
Notifications
You must be signed in to change notification settings - Fork 747
feat(amazonq): Add next edit suggestion #7555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
55b32d0
8772a2e
ea0bc1e
7db2529
9d7d3e1
b0ef943
6f37b23
3c67ade
a4ab56c
106f6ea
ff4dcc2
35362bc
6dafd10
dd4289d
896067b
696626d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| /*! | ||
| * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| // TODO: deprecate this file in favor of core/shared/utils/diffUtils | ||
| import { applyPatch } from 'diff' | ||
|
|
||
| export type LineDiff = | ||
| | { type: 'added'; content: string } | ||
| | { type: 'removed'; content: string } | ||
| | { type: 'modified'; before: string; after: string } | ||
|
|
||
| /** | ||
| * Apply a unified diff to original code to generate modified code | ||
| * @param originalCode The original code as a string | ||
| * @param unifiedDiff The unified diff content | ||
| * @returns The modified code after applying the diff | ||
| */ | ||
| export function applyUnifiedDiff( | ||
| docText: string, | ||
| unifiedDiff: string | ||
| ): { appliedCode: string; addedCharacterCount: number; deletedCharacterCount: number } { | ||
| try { | ||
| const { addedCharacterCount, deletedCharacterCount } = getAddedAndDeletedCharCount(unifiedDiff) | ||
| // First try the standard diff package | ||
| try { | ||
| const result = applyPatch(docText, unifiedDiff) | ||
| if (result !== false) { | ||
| return { | ||
| appliedCode: result, | ||
| addedCharacterCount: addedCharacterCount, | ||
| deletedCharacterCount: deletedCharacterCount, | ||
| } | ||
| } | ||
| } catch (error) {} | ||
|
|
||
| // Parse the unified diff to extract the changes | ||
| const diffLines = unifiedDiff.split('\n') | ||
| let result = docText | ||
|
|
||
| // Find all hunks in the diff | ||
| const hunkStarts = diffLines | ||
| .map((line, index) => (line.startsWith('@@ ') ? index : -1)) | ||
| .filter((index) => index !== -1) | ||
|
|
||
| // Process each hunk | ||
| for (const hunkStart of hunkStarts) { | ||
| // Parse the hunk header | ||
| const hunkHeader = diffLines[hunkStart] | ||
| const match = hunkHeader.match(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/) | ||
|
|
||
| if (!match) { | ||
| continue | ||
| } | ||
|
|
||
| const oldStart = parseInt(match[1]) | ||
| const oldLines = parseInt(match[2]) | ||
|
|
||
| // Extract the content lines for this hunk | ||
| let i = hunkStart + 1 | ||
| const contentLines = [] | ||
| while (i < diffLines.length && !diffLines[i].startsWith('@@')) { | ||
| contentLines.push(diffLines[i]) | ||
| i++ | ||
| } | ||
|
|
||
| // Build the old and new text | ||
| let oldText = '' | ||
| let newText = '' | ||
|
|
||
| for (const line of contentLines) { | ||
| if (line.startsWith('-')) { | ||
| oldText += line.substring(1) + '\n' | ||
| } else if (line.startsWith('+')) { | ||
| newText += line.substring(1) + '\n' | ||
| } else if (line.startsWith(' ')) { | ||
| oldText += line.substring(1) + '\n' | ||
| newText += line.substring(1) + '\n' | ||
| } | ||
| } | ||
|
|
||
| // Remove trailing newline if it was added | ||
| oldText = oldText.replace(/\n$/, '') | ||
| newText = newText.replace(/\n$/, '') | ||
|
|
||
| // Find the text to replace in the document | ||
| const docLines = docText.split('\n') | ||
| const startLine = oldStart - 1 // Convert to 0-based | ||
| const endLine = startLine + oldLines | ||
|
|
||
| // Extract the text that should be replaced | ||
| const textToReplace = docLines.slice(startLine, endLine).join('\n') | ||
|
|
||
| // Replace the text | ||
| result = result.replace(textToReplace, newText) | ||
| } | ||
| return { | ||
| appliedCode: result, | ||
| addedCharacterCount: addedCharacterCount, | ||
| deletedCharacterCount: deletedCharacterCount, | ||
| } | ||
| } catch (error) { | ||
| return { | ||
| appliedCode: docText, // Return original text if all methods fail | ||
| addedCharacterCount: 0, | ||
| deletedCharacterCount: 0, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| export function getAddedAndDeletedCharCount(diff: string): { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is no longer needed. I will make a followup PR to remove it. But it is not a blocker.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok will followup |
||
| addedCharacterCount: number | ||
| deletedCharacterCount: number | ||
| } { | ||
| let addedCharacterCount = 0 | ||
| let deletedCharacterCount = 0 | ||
| let i = 0 | ||
| const lines = diff.split('\n') | ||
| while (i < lines.length) { | ||
| const line = lines[i] | ||
| if (line.startsWith('+') && !line.startsWith('+++')) { | ||
| addedCharacterCount += line.length - 1 | ||
| } else if (line.startsWith('-') && !line.startsWith('---')) { | ||
| const removedLine = line.substring(1) | ||
| deletedCharacterCount += removedLine.length | ||
|
|
||
| // Check if this is a modified line rather than a pure deletion | ||
| const nextLine = lines[i + 1] | ||
| if (nextLine && nextLine.startsWith('+') && !nextLine.startsWith('+++') && nextLine.includes(removedLine)) { | ||
| // This is a modified line, not a pure deletion | ||
| // We've already counted the deletion, so we'll just increment i to skip the next line | ||
| // since we'll process the addition on the next iteration | ||
| i += 1 | ||
| } | ||
| } | ||
| i += 1 | ||
| } | ||
| return { | ||
| addedCharacterCount, | ||
| deletedCharacterCount, | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
followup: consolidate with
packages/core/src/shared/utilities/diffUtils.ts