Skip to content

Commit 5e9e2b4

Browse files
Will-ShaoHuadk19yfloralph
authored andcommitted
feat(amazonq): edit predition auto trigger (aws#1662)
Co-authored-by: Dhanasekar Karuppasamy <[email protected]> Co-authored-by: Flora <[email protected]>
1 parent a0483ab commit 5e9e2b4

File tree

3 files changed

+771
-0
lines changed

3 files changed

+771
-0
lines changed
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
/**
7+
* Position in a document
8+
*/
9+
export interface Position {
10+
line: number
11+
character: number
12+
}
13+
14+
/**
15+
* Scenario for testing cursor position triggers
16+
*/
17+
export interface CursorPositionScenario {
18+
name: string
19+
position: Position
20+
expectedTrigger: boolean
21+
isAfterKeyword?: boolean
22+
isAfterOperatorOrDelimiter?: boolean
23+
isAtLineBeginning?: boolean
24+
}
25+
26+
/**
27+
* Test scenarios for different programming languages
28+
*/
29+
export interface TestScenario {
30+
language: string
31+
code: string
32+
cursorPositionScenarios: CursorPositionScenario[]
33+
}
34+
35+
/**
36+
* Edit tracking test scenario
37+
*/
38+
export interface EditTrackingScenario {
39+
description: string
40+
uri: string
41+
checkLine: number
42+
timeThreshold: number
43+
expectedResult: boolean
44+
}
45+
46+
/**
47+
* Split code at a specific position
48+
*
49+
* @param code The full code string
50+
* @param position The position to split at
51+
* @returns Object containing left and right content
52+
*/
53+
export function splitCodeAtPosition(code: string, position: Position): { leftContent: string; rightContent: string } {
54+
const lines = code.split('\n')
55+
56+
// Get content before the position
57+
const leftLines = lines.slice(0, position.line)
58+
const currentLine = lines[position.line] || ''
59+
const leftPart = currentLine.substring(0, position.character)
60+
leftLines.push(leftPart)
61+
const leftContent = leftLines.join('\n')
62+
63+
// Get content after the position
64+
const rightPart = currentLine.substring(position.character)
65+
const rightLines = [rightPart, ...lines.slice(position.line + 1)]
66+
const rightContent = rightLines.join('\n')
67+
68+
// Ensure there's a non-empty suffix for testing
69+
if (rightLines.length > 1) {
70+
// Make sure the second line has content for the non-empty suffix check
71+
rightLines[1] = rightLines[1].trim() ? rightLines[1] : 'non-empty-suffix'
72+
return { leftContent, rightContent: rightLines.join('\n') }
73+
}
74+
75+
return { leftContent, rightContent: rightPart + '\nnon-empty-suffix' }
76+
}
77+
78+
/**
79+
* Test scenarios for different programming languages
80+
*/
81+
export const TestScenarios: Record<string, TestScenario> = {
82+
JAVA: {
83+
language: 'java',
84+
code: `public class Example {
85+
public static void main(String[] args) {
86+
System.out.println("Hello World");
87+
if (args.length > 0) {
88+
89+
}
90+
String name = "John";
91+
int x = 10;
92+
x += 5;
93+
}
94+
}`,
95+
cursorPositionScenarios: [
96+
{
97+
// "if █(args.length > 0) {"
98+
name: 'after if keyword',
99+
position: { line: 3, character: 11 },
100+
expectedTrigger: true,
101+
isAfterKeyword: true,
102+
},
103+
{
104+
// " █"
105+
name: 'inside empty block',
106+
position: { line: 4, character: 12 },
107+
expectedTrigger: true,
108+
isAtLineBeginning: true,
109+
},
110+
{
111+
// "String name = █"John";"
112+
name: 'after assignment operator',
113+
position: { line: 6, character: 20 },
114+
expectedTrigger: true,
115+
isAfterOperatorOrDelimiter: true,
116+
},
117+
{
118+
// "System.out.print█ln("Hello World");"
119+
name: 'middle of word',
120+
position: { line: 2, character: 18 },
121+
expectedTrigger: false,
122+
// Force this test to use the actual content check
123+
isAfterKeyword: false,
124+
isAfterOperatorOrDelimiter: false,
125+
isAtLineBeginning: false,
126+
},
127+
],
128+
},
129+
PYTHON: {
130+
language: 'python',
131+
code: `def example_function():
132+
print("Hello World")
133+
if True:
134+
135+
name = "John"
136+
x = 10
137+
x += 5`,
138+
cursorPositionScenarios: [
139+
{
140+
// "if █True:"
141+
name: 'after if keyword',
142+
position: { line: 2, character: 7 },
143+
expectedTrigger: true,
144+
isAfterKeyword: true,
145+
},
146+
{
147+
// " █"
148+
name: 'inside empty block',
149+
position: { line: 3, character: 8 },
150+
expectedTrigger: true,
151+
isAtLineBeginning: true,
152+
},
153+
{
154+
// "name = █"John""
155+
name: 'after assignment operator',
156+
position: { line: 4, character: 9 },
157+
expectedTrigger: true,
158+
isAfterOperatorOrDelimiter: true,
159+
},
160+
],
161+
},
162+
JAVASCRIPT: {
163+
language: 'javascript',
164+
code: `function example() {
165+
console.log("Hello World");
166+
if (true) {
167+
168+
}
169+
const name = "John";
170+
let x = 10;
171+
x += 5;
172+
}`,
173+
cursorPositionScenarios: [
174+
{
175+
// "if █(true) {"
176+
name: 'after if keyword',
177+
position: { line: 2, character: 7 },
178+
expectedTrigger: true,
179+
isAfterKeyword: true,
180+
},
181+
{
182+
// " █"
183+
name: 'inside empty block',
184+
position: { line: 3, character: 8 },
185+
expectedTrigger: true,
186+
isAtLineBeginning: true,
187+
},
188+
{
189+
// "const name = █"John";"
190+
name: 'after assignment operator',
191+
position: { line: 5, character: 17 },
192+
expectedTrigger: true,
193+
isAfterOperatorOrDelimiter: true,
194+
},
195+
],
196+
},
197+
}
198+
199+
/**
200+
* Test scenarios for edit tracking
201+
*/
202+
export const EditTrackingScenarios: Record<string, EditTrackingScenario> = {
203+
RECENT_EDIT_SAME_LINE: {
204+
description: 'Recent edit in the same line',
205+
uri: 'file:///test/document.java',
206+
checkLine: 5,
207+
timeThreshold: 5000,
208+
expectedResult: true,
209+
},
210+
NO_RECENT_EDIT: {
211+
description: 'No recent edit in the line',
212+
uri: 'file:///test/document.java',
213+
checkLine: 6,
214+
timeThreshold: 5000,
215+
expectedResult: false,
216+
},
217+
OLD_EDIT: {
218+
description: 'Edit is too old',
219+
uri: 'file:///test/document.java',
220+
checkLine: 5,
221+
timeThreshold: 1000, // Short threshold
222+
expectedResult: false,
223+
},
224+
DIFFERENT_DOCUMENT: {
225+
description: 'Edit in a different document',
226+
uri: 'file:///test/different-document.java',
227+
checkLine: 10,
228+
timeThreshold: 5000,
229+
expectedResult: false,
230+
},
231+
}

0 commit comments

Comments
 (0)