From 43b7689c95468c36fb7ea3d6f8eea06965ae22bb Mon Sep 17 00:00:00 2001 From: David Hasani Date: Tue, 26 Aug 2025 13:18:44 -0700 Subject: [PATCH 1/2] fix(amazonq): ensure plan opens for min JDK upgrades --- .../codemodernizer/CodeModernizerManager.kt | 4 +- .../codemodernizer/CodeModernizerSession.kt | 4 +- .../CodeModernizerBottomWindowPanelManager.kt | 7 ++- .../utils/CodeTransformApiUtils.kt | 9 ++- .../CodeWhispererCodeModernizerUtilsTest.kt | 58 +++++++++++++++++-- 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerManager.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerManager.kt index 77b95e0e255..ad40172b028 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerManager.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerManager.kt @@ -477,7 +477,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo transformType, jobId ) { new, plan -> - codeModernizerBottomWindowPanelManager.handleJobTransition(new, plan, session.sessionContext.sourceJavaVersion, transformType) + codeModernizerBottomWindowPanelManager.handleJobTransition(new, plan, session.sessionContext, transformType) } private suspend fun handleJobStarted(jobId: JobId, session: CodeModernizerSession): CodeModernizerJobCompletedResult { @@ -491,7 +491,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo val transformType = if (session.sessionContext.sqlMetadataZip != null) CodeTransformType.SQL_CONVERSION else CodeTransformType.LANGUAGE_UPGRADE return session.pollUntilJobCompletion(transformType, jobId) { new, plan -> - codeModernizerBottomWindowPanelManager.handleJobTransition(new, plan, session.sessionContext.sourceJavaVersion, transformType) + codeModernizerBottomWindowPanelManager.handleJobTransition(new, plan, session.sessionContext, transformType) } } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt index 7533259fd6d..0e4b7a14780 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt @@ -478,8 +478,8 @@ class CodeModernizerSession( } if (!isTransformationPlanEditorOpened && transformType == CodeTransformType.LANGUAGE_UPGRADE) { - val isPlanComplete = isPlanComplete(state.transformationPlan) - if (isPlanComplete) { + val isPlanComplete = isPlanComplete(state.transformationPlan, sessionContext) + if (isPlanComplete && state.transformationPlan != null) { tryOpenTransformationPlanEditor() isTransformationPlanEditorOpened = true } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt index eec38b73276..716c904facc 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt @@ -22,6 +22,7 @@ import software.amazon.awssdk.services.codewhispererruntime.model.Transformation import software.aws.toolkits.core.utils.getLogger import software.aws.toolkits.core.utils.warn import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerJobCompletedResult +import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformType import software.aws.toolkits.jetbrains.services.codemodernizer.panels.CodeModernizerBanner import software.aws.toolkits.jetbrains.services.codemodernizer.panels.CodeModernizerJobHistoryTablePanel @@ -244,7 +245,7 @@ class CodeModernizerBottomWindowPanelManager(private val project: Project) : JPa return actionManager.createActionToolbar(ACTION_PLACE, group, false) } - fun handleJobTransition(new: TransformationStatus, plan: TransformationPlan?, sourceJdk: JavaSdkVersion, transformType: CodeTransformType) = invokeLater { + fun handleJobTransition(new: TransformationStatus, plan: TransformationPlan?, sessionContext: CodeModernizerSessionContext, transformType: CodeTransformType) = invokeLater { if (new in listOf( TransformationStatus.PLANNED, TransformationStatus.TRANSFORMING, @@ -252,12 +253,12 @@ class CodeModernizerBottomWindowPanelManager(private val project: Project) : JPa TransformationStatus.PAUSED, TransformationStatus.COMPLETED, TransformationStatus.PARTIALLY_COMPLETED - ) && transformType == CodeTransformType.LANGUAGE_UPGRADE && isPlanComplete(plan) + ) && transformType == CodeTransformType.LANGUAGE_UPGRADE && isPlanComplete(plan, sessionContext) ) { addPlanToBanner() } buildProgressSplitterPanelManager.apply { - handleProgressStateChanged(new, plan, sourceJdk, transformType) + handleProgressStateChanged(new, plan, sessionContext.sourceJavaVersion, transformType) if (timer == null) { timer = Timer() timer?.scheduleAtFixedRate( diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index 915b3891ac8..4b6b3a85eea 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -47,6 +47,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.constants.BILLING import software.aws.toolkits.jetbrains.services.codemodernizer.constants.JOB_STATISTICS_TABLE_KEY import software.aws.toolkits.jetbrains.services.codemodernizer.ideMaven.runClientSideBuild import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerArtifact.Companion.MAPPER +import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformType import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId import software.aws.toolkits.jetbrains.services.codemodernizer.model.PlanTable @@ -286,8 +287,12 @@ fun findDownloadArtifactProgressUpdate(transformationSteps: List update.name() == "1" } == true +// plan is complete once dependency changes table (key of "1") available, or as soon as it's available for min JDK upgrades +fun isPlanComplete(plan: TransformationPlan?, sessionContext: CodeModernizerSessionContext): Boolean { + val isDepChangesTablePresent = plan?.transformationSteps()?.get(0)?.progressUpdates()?.any { update -> update.name() == "1" } == true + val isMinJdkUpgrade = sessionContext.sourceJavaVersion.name != sessionContext.targetJavaVersion.name + return isDepChangesTablePresent || isMinJdkUpgrade +} // "name" holds the ID of the corresponding plan step (where table will go) and "description" holds the plan data fun getTableMapping(stepZeroProgressUpdates: List): Map> = diff --git a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt index 16090b13437..f338b967090 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt @@ -4,6 +4,8 @@ package software.aws.toolkits.jetbrains.services.codemodernizer import com.fasterxml.jackson.module.kotlin.readValue +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.testFramework.LightVirtualFile import io.mockk.every import io.mockk.just @@ -16,6 +18,7 @@ import org.jetbrains.yaml.YAMLFileType import org.junit.Before import org.junit.Test import org.mockito.Mockito +import org.mockito.Mockito.mock import org.mockito.kotlin.any import org.mockito.kotlin.times import org.mockito.kotlin.verify @@ -28,6 +31,7 @@ import software.amazon.awssdk.services.codewhispererruntime.model.Transformation import software.amazon.awssdk.services.codewhispererruntime.model.TransformationStep import software.amazon.awssdk.services.ssooidc.model.InvalidGrantException import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerArtifact.Companion.MAPPER +import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformType import software.aws.toolkits.jetbrains.services.codemodernizer.model.PlanTable import software.aws.toolkits.jetbrains.services.codemodernizer.utils.combineTableRows @@ -53,6 +57,8 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase super.setup() } + private val mockProject: Project = mock(Project::class.java) + @Test fun `can poll for updates`() { Mockito.doReturn( @@ -254,7 +260,6 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase @Test fun `isPlanComplete returns true when plan has progress update with name '1'`() { - // Arrange val plan = TransformationPlan.builder() .transformationSteps( listOf( @@ -270,7 +275,15 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase ) ) .build() - val result = isPlanComplete(plan) + + // dependency upgrade + val sessionContext = CodeModernizerSessionContext( + project = mockProject, + sourceJavaVersion = JavaSdkVersion.JDK_17, + targetJavaVersion = JavaSdkVersion.JDK_17 + ) + + val result = isPlanComplete(plan, sessionContext) assertThat(result).isTrue() } @@ -283,7 +296,7 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase .progressUpdates( listOf( TransformationProgressUpdate.builder() - .name("2") + .name("not-1") .build() ) ) @@ -291,10 +304,47 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase ) ) .build() - val result = isPlanComplete(plan) + + // dependency upgrade + val sessionContext = CodeModernizerSessionContext( + project = mockProject, + sourceJavaVersion = JavaSdkVersion.JDK_17, + targetJavaVersion = JavaSdkVersion.JDK_17 + ) + + val result = isPlanComplete(plan, sessionContext) assertThat(result).isFalse() } + @Test + fun `isPlanComplete returns true when doing a min JDK upgrade`() { + val plan = TransformationPlan.builder() + .transformationSteps( + listOf( + TransformationStep.builder() + .progressUpdates( + listOf( + TransformationProgressUpdate.builder() + .name("not-1") + .build() + ) + ) + .build() + ) + ) + .build() + + // min JDK upgrade + val sessionContext = CodeModernizerSessionContext( + project = mockProject, + sourceJavaVersion = JavaSdkVersion.JDK_1_8, + targetJavaVersion = JavaSdkVersion.JDK_17 + ) + + val result = isPlanComplete(plan, sessionContext) + assertThat(result).isTrue() + } + @Test fun `getClientInstructionArtifactId extracts artifact ID from transformation plan`() { val step1 = TransformationStep.builder() From 3f6ae8642ef25abb7c3783abe02f957a784aa8fd Mon Sep 17 00:00:00 2001 From: David Hasani Date: Tue, 26 Aug 2025 15:00:35 -0700 Subject: [PATCH 2/2] fix detekt --- .../managers/CodeModernizerBottomWindowPanelManager.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt index 716c904facc..c846157c95b 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt @@ -245,7 +245,12 @@ class CodeModernizerBottomWindowPanelManager(private val project: Project) : JPa return actionManager.createActionToolbar(ACTION_PLACE, group, false) } - fun handleJobTransition(new: TransformationStatus, plan: TransformationPlan?, sessionContext: CodeModernizerSessionContext, transformType: CodeTransformType) = invokeLater { + fun handleJobTransition( + new: TransformationStatus, + plan: TransformationPlan?, + sessionContext: CodeModernizerSessionContext, + transformType: CodeTransformType, + ) = invokeLater { if (new in listOf( TransformationStatus.PLANNED, TransformationStatus.TRANSFORMING,