Skip to content

Commit bd2d61e

Browse files
dhasani23David Hasani
andauthored
fix(CodeTransform): pre-select Java version (#4401)
## Problem UX request to change the way we validate input: rather than letting user select a project, then run all validation checks, we want to run all validation checks on all open projects to filter valid projects for the user, plus pre-select the Java version for them if we were able to detect it and it's a supported version (8 or 11). ## Solution Implement what is described above. <!--- REMINDER: - Read CONTRIBUTING.md first. - Add test coverage for your changes. - Update the changelog using `npm run newChange`. - Link to related issues/commits. - Testing: how did you test your changes? - Screenshots --> ## License By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Co-authored-by: David Hasani <[email protected]>
1 parent 9da0a64 commit bd2d61e

File tree

5 files changed

+241
-142
lines changed

5 files changed

+241
-142
lines changed

packages/toolkit/src/codewhisperer/commands/startTransformByQ.ts

Lines changed: 80 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as fs from 'fs'
99
import * as os from 'os'
1010
import { getLogger } from '../../shared/logger'
1111
import * as CodeWhispererConstants from '../models/constants'
12-
import { transformByQState, StepProgress, TransformByQReviewStatus } from '../models/model'
12+
import { transformByQState, StepProgress, TransformByQReviewStatus, JDKVersion, DropdownStep } from '../models/model'
1313
import {
1414
throwIfCancelled,
1515
startJob,
@@ -21,10 +21,11 @@ import {
2121
convertToTimeString,
2222
convertDateToTimestamp,
2323
getOpenProjects,
24-
validateProjectSelection,
2524
getVersionData,
25+
validateOpenProjects,
2626
} from '../service/transformByQHandler'
2727
import { QuickPickItem } from 'vscode'
28+
import { MultiStepInputFlowController } from '../../shared//multiStepInputFlowController'
2829
import path from 'path'
2930
import { sleep } from '../../shared/utilities/timeoutUtils'
3031
import { encodeHTML } from '../../shared/utilities/textUtilities'
@@ -65,26 +66,82 @@ export async function startTransformByQWithProgress() {
6566
}
6667

6768
interface UserInputState {
68-
title: string
69-
step: number
70-
totalSteps: number
71-
targetLanguage: QuickPickItem
72-
targetVersion: QuickPickItem
73-
project: QuickPickItem
69+
project: QuickPickItem | undefined
70+
sourceJavaVersion: QuickPickItem | undefined
7471
}
7572

76-
async function collectInput(validProjects: vscode.QuickPickItem[]) {
73+
async function collectInput(validProjects: Map<vscode.QuickPickItem, JDKVersion | undefined>) {
7774
const state = {} as Partial<UserInputState>
78-
transformByQState.setTargetJDKVersionToJDK17()
79-
const pick = await vscode.window.showQuickPick(validProjects, {
75+
transformByQState.setTargetJDKVersion(JDKVersion.JDK17)
76+
await MultiStepInputFlowController.run(input => pickProject(input, state, validProjects))
77+
if (!state.project) {
78+
throw new ToolkitError('No project selected', { code: 'NoProjectSelected' })
79+
}
80+
const versionsArray = [JDKVersion.JDK8, JDKVersion.JDK11]
81+
const validSourceVersions: vscode.QuickPickItem[] = versionsArray.map(version => ({
82+
label: version,
83+
}))
84+
await MultiStepInputFlowController.run(input => pickSourceVersion(input, state, validSourceVersions))
85+
if (!state.sourceJavaVersion) {
86+
throw new ToolkitError('No version selected', { code: 'NoVersionSelected' })
87+
}
88+
return state as UserInputState
89+
}
90+
91+
async function pickProject(
92+
input: MultiStepInputFlowController,
93+
state: Partial<UserInputState>,
94+
validProjects: Map<vscode.QuickPickItem, JDKVersion | undefined>
95+
) {
96+
const pick = await input.showQuickPick({
97+
title: CodeWhispererConstants.transformByQWindowTitle,
98+
step: DropdownStep.STEP_1,
99+
totalSteps: DropdownStep.STEP_2,
100+
placeholder: CodeWhispererConstants.selectProjectPrompt,
101+
items: Array.from(validProjects.keys()),
102+
shouldResume: () => Promise.resolve(false),
103+
})
104+
state.project = pick
105+
transformByQState.setProjectName(encodeHTML(state.project.label)) // encode to avoid HTML injection risk
106+
const javaVersion = validProjects.get(pick)
107+
transformByQState.setSourceJDKVersion(javaVersion)
108+
}
109+
110+
async function pickSourceVersion(
111+
input: MultiStepInputFlowController,
112+
state: Partial<UserInputState>,
113+
validSourceVersions: vscode.QuickPickItem[]
114+
) {
115+
let detectedJavaVersion = undefined
116+
const sourceJDKVersion = transformByQState.getSourceJDKVersion()
117+
if (sourceJDKVersion === JDKVersion.JDK8) {
118+
detectedJavaVersion = validSourceVersions[0]
119+
} else if (sourceJDKVersion === JDKVersion.JDK11) {
120+
detectedJavaVersion = validSourceVersions[1]
121+
}
122+
let placeholderText = ''
123+
if (sourceJDKVersion === JDKVersion.JDK8 || sourceJDKVersion === JDKVersion.JDK11) {
124+
placeholderText = `We found Java ${sourceJDKVersion}. Select a different version if incorrect.`
125+
} else if (sourceJDKVersion === JDKVersion.UNSUPPORTED) {
126+
placeholderText = 'We found an unsupported Java version. Select your version here if incorrect.'
127+
} else {
128+
placeholderText = "Choose your project's Java version here." // if no .class files found or if javap fails
129+
}
130+
const pick = await input.showQuickPick({
80131
title: CodeWhispererConstants.transformByQWindowTitle,
81-
placeHolder: CodeWhispererConstants.selectModulePrompt,
132+
step: DropdownStep.STEP_2,
133+
totalSteps: DropdownStep.STEP_2,
134+
placeholder: placeholderText,
135+
items: validSourceVersions,
136+
activeItem: detectedJavaVersion,
137+
shouldResume: () => Promise.resolve(false),
82138
})
83-
if (pick) {
84-
state.project = pick
85-
transformByQState.setProjectName(encodeHTML(state.project.label)) // encode to avoid HTML injection risk
139+
state.sourceJavaVersion = pick
140+
if (pick === validSourceVersions[0]) {
141+
transformByQState.setSourceJDKVersion(JDKVersion.JDK8)
142+
} else if (pick === validSourceVersions[1]) {
143+
transformByQState.setSourceJDKVersion(JDKVersion.JDK11)
86144
}
87-
return state as UserInputState
88145
}
89146

90147
export async function startTransformByQ() {
@@ -135,7 +192,7 @@ export async function preTransformationUploadCode(userInputState: UserInputState
135192
let payloadFilePath = ''
136193
throwIfCancelled()
137194
try {
138-
payloadFilePath = await zipCode(userInputState.project.description!)
195+
payloadFilePath = await zipCode(userInputState.project!.description!)
139196
transformByQState.setPayloadFilePath(payloadFilePath)
140197
await vscode.commands.executeCommand('aws.amazonq.refresh') // so that button updates
141198
uploadId = await uploadPayload(payloadFilePath)
@@ -254,19 +311,17 @@ export async function validateTransformationJob() {
254311
getLogger().error('Failed to get open projects: ', err)
255312
throw err
256313
}
257-
const userInputState = await collectInput(openProjects)
258-
259-
if (!userInputState.project) {
260-
throw new ToolkitError('No project selected', { code: 'NoProjectSelected' })
261-
}
262314

315+
let validProjects = undefined
263316
try {
264-
await validateProjectSelection(userInputState.project)
317+
validProjects = await validateOpenProjects(openProjects)
265318
} catch (err) {
266319
getLogger().error('Selected project is not Java 8, not Java 11, or does not use Maven', err)
267320
throw err
268321
}
269322

323+
const userInputState = await collectInput(validProjects)
324+
270325
const selection = await vscode.window.showWarningMessage(
271326
CodeWhispererConstants.dependencyDisclaimer,
272327
{ modal: true },
@@ -291,7 +346,7 @@ export async function validateTransformationJob() {
291346

292347
export async function setTransformationToRunningState(userInputState: UserInputState) {
293348
transformByQState.setToRunning()
294-
transformByQState.setProjectPath(userInputState.project.description!)
349+
transformByQState.setProjectPath(userInputState.project!.description!)
295350
sessionPlanProgress['uploadCode'] = StepProgress.Pending
296351
sessionPlanProgress['buildCode'] = StepProgress.Pending
297352
sessionPlanProgress['transformCode'] = StepProgress.Pending
@@ -302,7 +357,7 @@ export async function setTransformationToRunningState(userInputState: UserInputS
302357
telemetry.codeTransform_jobStartedCompleteFromPopupDialog.emit({
303358
codeTransformSessionId: codeTransformTelemetryState.getSessionId(),
304359
codeTransformJavaSourceVersionsAllowed: JDKToTelemetryValue(
305-
transformByQState.getSourceJDKVersion()
360+
transformByQState.getSourceJDKVersion()!
306361
) as CodeTransformJavaSourceVersionsAllowed,
307362
codeTransformJavaTargetVersionsAllowed: JDKToTelemetryValue(
308363
transformByQState.getTargetJDKVersion()

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

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,9 @@ export const newCustomizationAvailableKey = 'CODEWHISPERER_NEW_CUSTOMIZATION_AVA
276276

277277
// Transform by Q
278278

279-
export const selectTargetLanguagePrompt = 'Select the target language'
279+
export const selectProjectPrompt = 'Select the project you want to transform'
280280

281-
export const selectTargetVersionPrompt = 'Select the target version'
282-
283-
export const selectModulePrompt = 'Select the module you want to transform'
284-
285-
export const transformByQWindowTitle = 'Amazon Q CodeTransformation'
281+
export const transformByQWindowTitle = 'Amazon Q Code Transformation'
286282

287283
export const stopTransformByQMessage = 'Stop Transformation?'
288284

@@ -297,9 +293,9 @@ export const transformByQCompletedMessage = 'Transformation completed'
297293
export const transformByQPartiallyCompletedMessage = 'Transformation partially completed'
298294

299295
export const noPomXmlFoundMessage =
300-
'We could not find a valid configuration file. We currently support Maven build tool and require a POM.xml in the root directory to identify build configurations. Be sure to also build your project.'
296+
'None of your open Java projects are supported by Amazon Q Code Transformation. We were unable to find a pom.xml in any of your Java projects. We only support Java projects built on Maven at the moment.'
301297

302-
export const noActiveIdCMessage = 'Transform by Q requires an active IAM Identity Center connection'
298+
export const noActiveIdCMessage = 'Amazon Q Code Transformation requires an active IAM Identity Center connection'
303299

304300
export const noOngoingJobMessage = 'No job is in-progress at the moment'
305301

@@ -309,18 +305,18 @@ export const cancellationInProgressMessage = 'Cancellation is in-progress'
309305

310306
export const errorStoppingJobMessage = 'Error stopping job'
311307

312-
export const errorDownloadingDiffMessage = 'Transform by Q experienced an error when downloading the diff'
308+
export const errorDownloadingDiffMessage = 'Amazon Q Code Transformation experienced an error when downloading the diff'
313309

314310
export const viewProposedChangesMessage =
315311
'Transformation job completed. You can view the transformation summary along with the proposed changes and accept or reject them in the Proposed Changes panel.'
316312

317313
export const changesAppliedMessage = 'Changes applied'
318314

319315
export const noSupportedJavaProjectsFoundMessage =
320-
'We could not find an upgrade-eligible application. We currently support upgrade of Java applications of version 8 and 11. Be sure to also build your project.'
316+
'None of your open projects are supported by Amazon Q Code Transformation. We were unable to find a Java project. We only support Java projects built on Maven at the moment.'
321317

322318
export const dependencyDisclaimer =
323-
'Please confirm you are ready to proceed with the transformation. Amazon Q will upload the application code and its dependency binaries from your machine to start the upgrade. If you have not yet compiled the application on your local machine, please do so once before starting the upgrade. Install Maven to ensure all module dependencies are picked for Transformation.'
319+
'Please confirm you are ready to proceed with the transformation. Amazon Q Code Transformation will upload the application code and its dependency binaries from your machine to start the upgrade. If you have not yet compiled the application on your local machine, please do so once before starting the upgrade. Install Maven to ensure all module dependencies are picked for Transformation.'
324320

325321
export const dependencyFolderName = 'transformation_dependencies_temp_'
326322

packages/toolkit/src/codewhisperer/models/model.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export enum JDKVersion {
240240
JDK8 = '8',
241241
JDK11 = '11',
242242
JDK17 = '17',
243+
UNSUPPORTED = 'UNSUPPORTED',
243244
}
244245

245246
export enum BuildSystem {
@@ -254,6 +255,11 @@ export class ZipManifest {
254255
version: string = '1.0'
255256
}
256257

258+
export enum DropdownStep {
259+
STEP_1 = 1,
260+
STEP_2 = 2,
261+
}
262+
257263
export class TransformByQState {
258264
private transformByQState: TransformByQStatus = TransformByQStatus.NotStarted
259265

@@ -262,7 +268,7 @@ export class TransformByQState {
262268

263269
private jobId: string = ''
264270

265-
private sourceJDKVersion: JDKVersion = JDKVersion.JDK8
271+
private sourceJDKVersion: JDKVersion | undefined = undefined
266272

267273
private targetJDKVersion: JDKVersion = JDKVersion.JDK17
268274

@@ -406,16 +412,12 @@ export class TransformByQState {
406412
this.jobId = id
407413
}
408414

409-
public setSourceJDKVersionToJDK8() {
410-
this.sourceJDKVersion = JDKVersion.JDK8
411-
}
412-
413-
public setSourceJDKVersionToJDK11() {
414-
this.sourceJDKVersion = JDKVersion.JDK11
415+
public setSourceJDKVersion(version: JDKVersion | undefined) {
416+
this.sourceJDKVersion = version
415417
}
416418

417-
public setTargetJDKVersionToJDK17() {
418-
this.targetJDKVersion = JDKVersion.JDK17
419+
public setTargetJDKVersion(version: JDKVersion) {
420+
this.targetJDKVersion = version
419421
}
420422

421423
public setPlanFilePath(filePath: string) {

0 commit comments

Comments
 (0)