Skip to content

Commit 5687fbd

Browse files
author
David Hasani
committed
parse plan
1 parent 5c28a36 commit 5687fbd

File tree

6 files changed

+133
-17
lines changed

6 files changed

+133
-17
lines changed

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import software.amazon.awssdk.services.codewhispererruntime.model.StartTransform
1717
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationJob
1818
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationLanguage
1919
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationPlan
20+
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationProgressUpdate
2021
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationProgressUpdateStatus
2122
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationStatus
23+
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationStep
2224
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationUserActionStatus
2325
import software.amazon.awssdk.services.codewhispererruntime.model.UploadContext
2426
import software.amazon.awssdk.services.codewhispererstreaming.model.TransformationDownloadArtifactType
@@ -608,7 +610,72 @@ class CodeModernizerSession(
608610
}
609611

610612
fun tryOpenTransformationPlanEditor() {
611-
val transformationPlan = getTransformationPlan()
613+
// var transformationPlan = getTransformationPlan()
614+
// TODO: remove this mocked API response
615+
val transformationPlan = TransformationPlan.builder()
616+
.transformationSteps(
617+
listOf(
618+
TransformationStep.builder()
619+
.id("0")
620+
.name("Supplement Info")
621+
.status("COMPLETED")
622+
.progressUpdates(
623+
listOf(
624+
TransformationProgressUpdate.builder()
625+
.name("0")
626+
.status("COMPLETED")
627+
.description("{\"type\":\"STATISTICS\",\"name\":\"Plan Statistics\",\"description\":null,\"columnNames\":[\"name\",\"value\"],\"rows\":[{\"name\":\"linesOfCode\",\"value\":\"2532\"},{\"name\":\"plannedDependencyChanges\",\"value\":\"4\"},{\"name\":\"plannedDeprecatedApiChanges\",\"value\":\"0\"},{\"name\":\"plannedFileChanges\",\"value\":\"7\"}]}")
628+
.build(),
629+
TransformationProgressUpdate.builder()
630+
.name("1")
631+
.status("COMPLETED")
632+
.description("{\"type\":\"DEPENDENCIES\",\"name\":\"Dependency Changes\",\"description\":null,\"columnNames\":[\"dependencyName\",\"action\",\"currentVersion\",\"targetVersion\"],\"rows\":[{\"dependencyName\":\"junit:junit\",\"action\":\"REMOVE\",\"currentVersion\":\"4.12\",\"targetVersion\":\"-\"},{\"dependencyName\":\"org.apache.logging.log4j:log4j-slf4j-impl\",\"action\":\"ADD\",\"currentVersion\":\"-\",\"targetVersion\":\"2.x\"},{\"dependencyName\":\"org.apache.maven.plugins:maven-surefire-plugin\",\"action\":\"UPDATE\",\"currentVersion\":\"2.18.1\",\"targetVersion\":\"3.1.x\"},{\"dependencyName\":\"org.slf4j:slf4j-log4j12\",\"action\":\"REMOVE\",\"currentVersion\":\"1.8.0-beta0\",\"targetVersion\":\"-\"}]}")
633+
.build(),
634+
TransformationProgressUpdate.builder()
635+
.name("1")
636+
.status("COMPLETED")
637+
.description("{\"type\":\"DEPENDENCIES\",\"name\":\"Dependency Changes\",\"description\":null,\"columnNames\":[\"dependencyName\",\"action\",\"currentVersion\",\"targetVersion\"],\"rows\":[{\"dependencyName\":\"junit:junit\",\"action\":\"REMOVE\",\"currentVersion\":\"4.12\",\"targetVersion\":\"-\"},{\"dependencyName\":\"org.apache.logging.log4j:log4j-slf4j-impl\",\"action\":\"ADD\",\"currentVersion\":\"-\",\"targetVersion\":\"2.x\"},{\"dependencyName\":\"org.apache.maven.plugins:maven-surefire-plugin\",\"action\":\"UPDATE\",\"currentVersion\":\"2.18.1\",\"targetVersion\":\"3.1.x\"},{\"dependencyName\":\"org.slf4j:slf4j-log4j12\",\"action\":\"REMOVE\",\"currentVersion\":\"1.8.0-beta0\",\"targetVersion\":\"-\"}]}")
638+
.build(),
639+
TransformationProgressUpdate.builder()
640+
.name("1")
641+
.status("COMPLETED")
642+
.description("{\"type\":\"DEPENDENCIES\",\"name\":\"Dependency Changes\",\"description\":null,\"columnNames\":[\"dependencyName\",\"action\",\"currentVersion\",\"targetVersion\"],\"rows\":[{\"dependencyName\":\"com.squareup.okio:okio\",\"action\":\"UPDATE\",\"currentVersion\":\"4.12\",\"targetVersion\":\"-\"},{\"dependencyName\":\"org.apache.logging.log4j:log4j-slf4j-impl\",\"action\":\"ADD\",\"currentVersion\":\"-\",\"targetVersion\":\"2.x\"},{\"dependencyName\":\"org.apache.maven.plugins:maven-surefire-plugin\",\"action\":\"UPDATE\",\"currentVersion\":\"2.18.1\",\"targetVersion\":\"3.1.x\"},{\"dependencyName\":\"org.slf4j:slf4j-log4j12\",\"action\":\"REMOVE\",\"currentVersion\":\"1.8.0-beta0\",\"targetVersion\":\"-\"}]}")
643+
.build(),
644+
TransformationProgressUpdate.builder()
645+
.name("1")
646+
.status("COMPLETED")
647+
.description("{\"type\":\"DEPENDENCIES\",\"name\":\"Dependency Changes\",\"description\":null,\"columnNames\":[\"dependencyName\",\"action\",\"currentVersion\",\"targetVersion\"],\"rows\":[{\"dependencyName\":\"com.squareup.okio:okio\",\"action\":\"UPDATE\",\"currentVersion\":\"4.12\",\"targetVersion\":\"-\"},{\"dependencyName\":\"org.apache.logging.log4j:log4j-slf4j-impl\",\"action\":\"ADD\",\"currentVersion\":\"-\",\"targetVersion\":\"2.x\"},{\"dependencyName\":\"org.apache.maven.plugins:maven-surefire-plugin\",\"action\":\"UPDATE\",\"currentVersion\":\"2.18.1\",\"targetVersion\":\"3.1.x\"},{\"dependencyName\":\"org.slf4j:slf4j-log4j12\",\"action\":\"REMOVE\",\"currentVersion\":\"1.8.0-beta0\",\"targetVersion\":\"-\"}]}")
648+
.build(),
649+
TransformationProgressUpdate.builder()
650+
.name("1")
651+
.status("COMPLETED")
652+
.description("{\"type\":\"DEPENDENCIES\",\"name\":\"Dependency Changes\",\"description\":null,\"columnNames\":[\"dependencyName\",\"action\",\"currentVersion\",\"targetVersion\"],\"rows\":[{\"dependencyName\":\"com.squareup.okio:okio\",\"action\":\"UPDATE\",\"currentVersion\":\"4.12\",\"targetVersion\":\"-\"},{\"dependencyName\":\"org.apache.logging.log4j:log4j-slf4j-impl\",\"action\":\"ADD\",\"currentVersion\":\"-\",\"targetVersion\":\"2.x\"},{\"dependencyName\":\"org.apache.maven.plugins:maven-surefire-plugin\",\"action\":\"UPDATE\",\"currentVersion\":\"2.18.1\",\"targetVersion\":\"3.1.x\"},{\"dependencyName\":\"org.slf4j:slf4j-log4j12\",\"action\":\"REMOVE\",\"currentVersion\":\"1.8.0-beta0\",\"targetVersion\":\"-\"}]}")
653+
.build(),
654+
TransformationProgressUpdate.builder()
655+
.name("-1")
656+
.status("COMPLETED")
657+
.description("{\"type\":\"FILES\",\"name\":\"File Changes\",\"description\":null,\"columnNames\":[\"relativePath\",\"action\"],\"rows\":[{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/TopLevelInterfaceTest.java\",\"action\":\"UPDATE\"},{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/TopLevelEnumerationTest.java\",\"action\":\"UPDATE\"},{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/TopLevelClassTest.java\",\"action\":\"UPDATE\"},{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/TopLevelAnnotationTest.java\",\"action\":\"UPDATE\"},{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/ParameterTest.java\",\"action\":\"UPDATE\"},{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/MethodTest.java\",\"action\":\"UPDATE\"},{\"relativePath\":\"src/main/test/com/nxllxn/plantuml/java/FieldTest.java\",\"action\":\"UPDATE\"}]}")
658+
.build()
659+
)
660+
)
661+
.build(),
662+
TransformationStep.builder()
663+
.id("1")
664+
.name("Step 1 - Update JDK version, dependencies and related code (David)")
665+
.description("Amazon Q will attempt to update the JDK version and change the following dependencies and related code.")
666+
.status("CREATED")
667+
.progressUpdates(emptyList())
668+
.build(),
669+
TransformationStep.builder()
670+
.id("2")
671+
.name("Step 2 - Finalize code changes")
672+
.description("Amazon Q will attempt to replace the following instances of deprecated code.")
673+
.status("CREATED")
674+
.progressUpdates(emptyList())
675+
.build()
676+
)
677+
)
678+
.build()
612679
if (transformationPlan != null) {
613680
runInEdt {
614681
CodeModernizerPlanEditorProvider.openEditor(

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/PlanTable.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ data class PlanTable(
1111
@JsonProperty("columnNames")
1212
val columns: List<String>,
1313
@JsonProperty("rows")
14-
val rows: List<PlanTableRow>,
14+
val rows: MutableList<PlanTableRow>,
1515
@JsonProperty("name")
1616
val name: String,
1717
)

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ data class ZipManifest(
1111
val version: String = UPLOAD_ZIP_MANIFEST_VERSION,
1212
val hilCapabilities: List<String> = listOf(HIL_1P_UPGRADE_CAPABILITY),
1313
// TODO: add CLIENT_SIDE_BUILD to transformCapabilities when releasing CSB
14+
15+
// TODO: add AGENTIC_PLAN_V1 or something here
16+
1417
val transformCapabilities: List<String> = listOf(EXPLAINABILITY_V1),
1518
val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS,
1619
val requestedConversions: RequestedConversions? = null, // only used for SQL conversions for now

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/plan/CodeModernizerPlanEditor.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.constants.LOC_THR
2424
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerArtifact.Companion.MAPPER
2525
import software.aws.toolkits.jetbrains.services.codemodernizer.model.PlanTable
2626
import software.aws.toolkits.jetbrains.services.codemodernizer.plan.CodeModernizerPlanEditorProvider.Companion.MIGRATION_PLAN_KEY
27+
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.combineTableRows
2728
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getAuthType
2829
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getBillingText
2930
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getLinesOfCodeSubmitted
@@ -103,10 +104,10 @@ class CodeModernizerPlanEditor(val project: Project, private val virtualFile: Vi
103104
)
104105
}
105106
add(transformationPlanPanel(plan), CodeModernizerUIConstants.transformationPlanPlaneConstraint)
106-
// key "-1" reserved for appendix table
107+
// key "-1" reserved for appendix table; only 1 table there
107108
if (APPENDIX_TABLE_KEY in tableMapping) {
108109
add(
109-
tableMapping[APPENDIX_TABLE_KEY]?.let { MAPPER.readValue<PlanTable>(it) }?.let { transformationPlanAppendix(it) },
110+
tableMapping[APPENDIX_TABLE_KEY]?.get(0)?.let { MAPPER.readValue<PlanTable>(it) }?.let { transformationPlanAppendix(it) },
110111
CodeModernizerUIConstants.transformationPlanPlaneConstraint,
111112
)
112113
}
@@ -393,10 +394,17 @@ class CodeModernizerPlanEditor(val project: Project, private val virtualFile: Vi
393394
border = CodeModernizerUIConstants.DESCRIPTION_BORDER
394395
}
395396

396-
val table = tableMapping[step.id()]
397+
val tables = tableMapping[step.id()]
397398

398-
var parsedTable = table?.let {
399-
MAPPER.readValue<PlanTable>(it)
399+
val parsedTables = tables?.map { table ->
400+
MAPPER.readValue<PlanTable>(table)
401+
}
402+
403+
var parsedTable: PlanTable? = if (parsedTables?.size == 1) {
404+
parsedTables.first()
405+
} else {
406+
// for multiple tables under 1 step, the table headers are the same, so combine the rows and just show 1 combined table
407+
combineTableRows(parsedTables)
400408
}
401409

402410
if (parsedTable?.rows?.isEmpty() == true) {

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -286,19 +286,33 @@ fun findDownloadArtifactProgressUpdate(transformationSteps: List<TransformationS
286286
}
287287

288288
// "name" holds the ID of the corresponding plan step (where table will go) and "description" holds the plan data
289-
fun getTableMapping(stepZeroProgressUpdates: List<TransformationProgressUpdate>): Map<String, String> {
290-
if (stepZeroProgressUpdates.isNotEmpty()) {
291-
return stepZeroProgressUpdates.associate {
292-
it.name() to it.description()
289+
fun getTableMapping(stepZeroProgressUpdates: List<TransformationProgressUpdate>): Map<String, List<String>> {
290+
return stepZeroProgressUpdates.groupBy(
291+
{ it.name() },
292+
{ it.description() }
293+
)
294+
}
295+
296+
// ID of '0' reserved for job statistics table; only 1 table there
297+
fun parseTableMapping(tableMapping: Map<String, List<String>>): PlanTable {
298+
val statsTable = tableMapping[JOB_STATISTICS_TABLE_KEY]?.get(0) ?: error("No transformation statistics table found in GetPlan response")
299+
return MAPPER.readValue<PlanTable>(statsTable)
300+
}
301+
302+
// columns and name are shared between all PlanTables, so just combine the rows here
303+
fun combineTableRows(tables: List<PlanTable>?): PlanTable? {
304+
if (tables == null) {
305+
return null
306+
}
307+
val combinedTable = PlanTable(tables.first().columns, mutableListOf(), tables.first().name)
308+
tables.forEach { table ->
309+
table.rows.forEach { row ->
310+
combinedTable.rows.add(row)
293311
}
294-
} else {
295-
error("GetPlan response missing step 0 progress updates with table data")
296312
}
313+
return combinedTable
297314
}
298315

299-
fun parseTableMapping(tableMapping: Map<String, String>): PlanTable? =
300-
tableMapping[JOB_STATISTICS_TABLE_KEY]?.let { MAPPER.readValue<PlanTable>(it) }
301-
302316
fun getBillingText(linesOfCode: Int): String {
303317
val estimatedCost = String.format(Locale.US, "%.2f", linesOfCode.times(BILLING_RATE))
304318
return message("codemodernizer.migration_plan.header.billing_text", linesOfCode, BILLING_RATE, estimatedCost)

plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
package software.aws.toolkits.jetbrains.services.codemodernizer
55

6+
import com.fasterxml.jackson.module.kotlin.readValue
67
import com.intellij.testFramework.LightVirtualFile
78
import io.mockk.every
89
import io.mockk.just
@@ -26,7 +27,10 @@ import software.amazon.awssdk.services.codewhispererruntime.model.Transformation
2627
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationStatus
2728
import software.amazon.awssdk.services.codewhispererruntime.model.TransformationStep
2829
import software.amazon.awssdk.services.ssooidc.model.InvalidGrantException
30+
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerArtifact.Companion.MAPPER
2931
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformType
32+
import software.aws.toolkits.jetbrains.services.codemodernizer.model.PlanTable
33+
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.combineTableRows
3034
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.createClientSideBuildUploadZip
3135
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getBillingText
3236
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getClientInstructionArtifactId
@@ -224,10 +228,30 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase
224228
val step0Update2 = TransformationProgressUpdate.builder().name("2").status("COMPLETED").description(apiChanges).build()
225229
val step0Update3 = TransformationProgressUpdate.builder().name("-1").status("COMPLETED").description(fileChanges).build()
226230
val actual = getTableMapping(listOf(step0Update0, step0Update1, step0Update2, step0Update3))
227-
val expected = mapOf("0" to jobStats, "1" to depChanges, "2" to apiChanges, "-1" to fileChanges)
231+
val expected = mapOf("0" to listOf(jobStats), "1" to listOf(depChanges), "2" to listOf(apiChanges), "-1" to listOf(fileChanges))
228232
assertThat(expected).isEqualTo(actual)
229233
}
230234

235+
@Test
236+
fun `combineTableRows combines multiple dependency tables correctly`() {
237+
val table1Json = """
238+
{"name":"Dependency changes", "columnNames":["dependencyName","action","currentVersion","targetVersion"],
239+
"rows":[{"dependencyName":"org.springframework.boot","action":"Update","currentVersion":"2.1","targetVersion":"2.4"}]}
240+
""".trimIndent()
241+
val table2Json = """
242+
{"name":"Dependency changes", "columnNames":["dependencyName","action","currentVersion","targetVersion"],
243+
"rows":[{"dependencyName":"junit","action":"Add","currentVersion":"","targetVersion":"4.13"}]}
244+
""".trimIndent()
245+
val tables = listOf(
246+
MAPPER.readValue<PlanTable>(table1Json),
247+
MAPPER.readValue<PlanTable>(table2Json)
248+
)
249+
val combinedTable = combineTableRows(tables)
250+
assertThat(combinedTable?.rows).hasSize(2)
251+
assertThat(combinedTable?.name).isEqualTo("Dependency changes")
252+
assertThat(combinedTable?.columns).hasSize(4)
253+
}
254+
231255
@Test
232256
fun `getClientInstructionArtifactId extracts artifact ID from transformation plan`() {
233257
val step1 = TransformationStep.builder()

0 commit comments

Comments
 (0)