From e10d8808ac2b20789f3e8c4f3b16f3150ca80cb6 Mon Sep 17 00:00:00 2001 From: lalexcaws Date: Wed, 25 Sep 2024 10:15:26 -0700 Subject: [PATCH 1/2] feat(telemetry): Include user intent for copy and insert code interactions (#4903) --- .../services/cwc/controller/chat/telemetry/TelemetryHelper.kt | 2 ++ .../toolkits/jetbrains/services/cwc/messages/CwcMessage.kt | 3 +++ .../jetbrains/services/amazonq/TelemetryHelperTest.kt | 3 +++ .../core/jetbrains-community/resources/telemetryOverride.json | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/controller/chat/telemetry/TelemetryHelper.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/controller/chat/telemetry/TelemetryHelper.kt index 3c9676a440..22ac5d7fe7 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/controller/chat/telemetry/TelemetryHelper.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/controller/chat/telemetry/TelemetryHelper.kt @@ -210,6 +210,7 @@ class TelemetryHelper(private val context: AmazonQAppInitContext, private val se AmazonqTelemetry.interactWithMessage( cwsprChatConversationId = getConversationId(message.tabId).orEmpty(), cwsprChatMessageId = message.messageId, + cwsprChatUserIntent = message.userIntent?.let { getTelemetryUserIntent(it) }, cwsprChatInteractionType = CwsprChatInteractionType.CopySnippet, cwsprChatAcceptedCharactersLength = message.code.length.toLong(), cwsprChatInteractionTarget = message.insertionTargetType, @@ -233,6 +234,7 @@ class TelemetryHelper(private val context: AmazonQAppInitContext, private val se AmazonqTelemetry.interactWithMessage( cwsprChatConversationId = getConversationId(message.tabId).orEmpty(), cwsprChatMessageId = message.messageId, + cwsprChatUserIntent = message.userIntent?.let { getTelemetryUserIntent(it) }, cwsprChatInteractionType = CwsprChatInteractionType.InsertAtCursor, cwsprChatAcceptedCharactersLength = message.code.length.toLong(), cwsprChatAcceptedNumberOfLines = message.code.lines().size.toLong(), diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt index dd7d9485b2..674c6f058e 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt @@ -13,6 +13,7 @@ import com.fasterxml.jackson.databind.JsonSerializer import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonSerialize +import software.amazon.awssdk.services.codewhispererstreaming.model.UserIntent import software.aws.toolkits.jetbrains.services.amazonq.auth.AuthFollowUpType import software.aws.toolkits.jetbrains.services.amazonq.messages.AmazonQMessage import software.aws.toolkits.jetbrains.services.amazonq.onboarding.OnboardingPageInteractionType @@ -65,6 +66,7 @@ sealed interface IncomingCwcMessage : CwcMessage { val command: String?, @JsonProperty("tabID") val tabId: String, val messageId: String, + val userIntent: UserIntent?, val code: String, val insertionTargetType: String?, val eventId: String?, @@ -75,6 +77,7 @@ sealed interface IncomingCwcMessage : CwcMessage { data class InsertCodeAtCursorPosition( @JsonProperty("tabID") val tabId: String, val messageId: String, + val userIntent: UserIntent?, val code: String, val insertionTargetType: String?, val codeReference: List?, diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/TelemetryHelperTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/TelemetryHelperTest.kt index f8878f68b4..0cba45227e 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/TelemetryHelperTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/TelemetryHelperTest.kt @@ -106,6 +106,7 @@ class TelemetryHelperTest { private const val mockRegion = "us-east-1" private const val tabId = "tabId" private const val messageId = "messageId" + private val userIntent = UserIntent.SHOW_EXAMPLES private const val conversationId = "conversationId" private const val triggerId = "triggerId" private const val customizationArn = "customizationArn" @@ -414,6 +415,7 @@ class TelemetryHelperTest { "command", tabId, messageId, + userIntent, "println()", "insertionTargetType", "eventId", @@ -476,6 +478,7 @@ class TelemetryHelperTest { IncomingCwcMessage.InsertCodeAtCursorPosition( tabId, messageId, + userIntent, code, inserTionTargetType, emptyList(), diff --git a/plugins/core/jetbrains-community/resources/telemetryOverride.json b/plugins/core/jetbrains-community/resources/telemetryOverride.json index 8e43b8e747..e3e8bee136 100644 --- a/plugins/core/jetbrains-community/resources/telemetryOverride.json +++ b/plugins/core/jetbrains-community/resources/telemetryOverride.json @@ -653,6 +653,10 @@ { "type": "cwsprChatMessageId" }, + { + "type": "cwsprChatUserIntent", + "required": false + }, { "type": "cwsprChatInteractionType" }, From fa3dcf2e4444f7f7fe169b3b3aad2cde34526ed3 Mon Sep 17 00:00:00 2001 From: David <60020664+dhasani23@users.noreply.github.com> Date: Wed, 25 Sep 2024 10:53:53 -0700 Subject: [PATCH 2/2] feat(amazonq): allow users to skip tests (#4887) Prompt the user with a form asking them if they want us to skip integ tests or skip all tests when doing our server-side build. Pass the flag via the manifest.json. --- ...-e16b5994-34c8-465b-b0a9-386590a7d9ea.json | 4 ++ .../codemodernizer/CodeModernizerManager.kt | 27 +++++------ .../codemodernizer/CodeTransformChatApp.kt | 3 ++ .../InboundAppMessagesHandler.kt | 2 + .../constants/CodeTransformChatItems.kt | 46 +++++++++++++++++-- .../controller/CodeTransformChatController.kt | 46 +++++++++++++++---- .../messages/CodeTransformMessage.kt | 7 +++ .../model/CodeModernizerSessionContext.kt | 5 +- .../codemodernizer/model/CustomerSelection.kt | 2 +- .../codemodernizer/model/ZipManifest.kt | 3 +- .../state/CodeModernizerState.kt | 11 ++++- .../CodeWhispererCodeModernizerSessionTest.kt | 8 +++- .../CodeWhispererCodeModernizerTestBase.kt | 3 +- .../ui/apps/codeTransformChatConnector.ts | 7 +++ .../mynah-ui/src/mynah-ui/ui/commands.ts | 1 + .../src/mynah-ui/ui/forms/constants.ts | 2 + .../resources/MessagesBundle.properties | 15 ++++-- 17 files changed, 150 insertions(+), 42 deletions(-) create mode 100644 .changes/next-release/feature-e16b5994-34c8-465b-b0a9-386590a7d9ea.json diff --git a/.changes/next-release/feature-e16b5994-34c8-465b-b0a9-386590a7d9ea.json b/.changes/next-release/feature-e16b5994-34c8-465b-b0a9-386590a7d9ea.json new file mode 100644 index 0000000000..629148e276 --- /dev/null +++ b/.changes/next-release/feature-e16b5994-34c8-465b-b0a9-386590a7d9ea.json @@ -0,0 +1,4 @@ +{ + "type" : "feature", + "description" : "Amazon Q Code Transformation: allow users to skip tests" +} \ No newline at end of file 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 4d5e6e4639..f3efe807d3 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 @@ -112,7 +112,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo private val isJobSuccessfullyResumed = AtomicBoolean(false) private val transformationStoppedByUsr = AtomicBoolean(false) - private var codeTransformationSession: CodeModernizerSession? = null + var codeTransformationSession: CodeModernizerSession? = null set(session) { if (session != null) { Disposer.register(this, session) @@ -383,12 +383,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo CodeTransformMessageListener.instance.onMavenBuildResult(mavenCopyCommandsResult) } - fun runLocalMavenBuild(project: Project, customerSelection: CustomerSelection) { - // Create and set a session - codeTransformationSession = null - val session = createCodeModernizerSession(customerSelection, project) - codeTransformationSession = session - + fun runLocalMavenBuild(project: Project, session: CodeModernizerSession) { projectCoroutineScope(project).launch { isMvnRunning.set(true) val result = session.getDependenciesUsingMaven() @@ -668,14 +663,16 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo telemetry.totalRunTime(result.toString(), jobId) } - fun createCodeModernizerSession(customerSelection: CustomerSelection, project: Project) = CodeModernizerSession( - CodeModernizerSessionContext( - project, - customerSelection.configurationFile, - customerSelection.sourceJavaVersion, - customerSelection.targetJavaVersion, - ), - ) + fun createCodeModernizerSession(customerSelection: CustomerSelection, project: Project) { + codeTransformationSession = CodeModernizerSession( + CodeModernizerSessionContext( + project, + customerSelection.configurationFile, + customerSelection.sourceJavaVersion, + customerSelection.targetJavaVersion, + ), + ) + } fun showModernizationProgressUI() = codeModernizerBottomWindowPanelManager.showUnalteredJobUI() diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeTransformChatApp.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeTransformChatApp.kt index ef3e7def37..4077362f11 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeTransformChatApp.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeTransformChatApp.kt @@ -35,6 +35,7 @@ private enum class CodeTransformMessageTypes(val type: String) { CodeTransformStart("codetransform-start"), CodeTransformStop("codetransform-stop"), CodeTransformCancel("codetransform-cancel"), + CodeTransformConfirmSkipTests("codetransform-confirm-skip-tests"), CodeTransformNew("codetransform-new"), CodeTransformOpenTransformHub("codetransform-open-transform-hub"), CodeTransformOpenMvnBuild("codetransform-open-mvn-build"), @@ -64,6 +65,7 @@ class CodeTransformChatApp : AmazonQApp { CodeTransformMessageTypes.CodeTransformStart.type to IncomingCodeTransformMessage.CodeTransformStart::class, CodeTransformMessageTypes.CodeTransformStop.type to IncomingCodeTransformMessage.CodeTransformStop::class, CodeTransformMessageTypes.CodeTransformCancel.type to IncomingCodeTransformMessage.CodeTransformCancel::class, + CodeTransformMessageTypes.CodeTransformConfirmSkipTests.type to IncomingCodeTransformMessage.CodeTransformConfirmSkipTests::class, CodeTransformMessageTypes.CodeTransformNew.type to IncomingCodeTransformMessage.CodeTransformNew::class, CodeTransformMessageTypes.CodeTransformOpenTransformHub.type to IncomingCodeTransformMessage.CodeTransformOpenTransformHub::class, CodeTransformMessageTypes.CodeTransformOpenMvnBuild.type to IncomingCodeTransformMessage.CodeTransformOpenMvnBuild::class, @@ -153,6 +155,7 @@ class CodeTransformChatApp : AmazonQApp { is IncomingCodeTransformMessage.CodeTransformStart -> inboundAppMessagesHandler.processCodeTransformStartAction(message) is IncomingCodeTransformMessage.CodeTransformCancel -> inboundAppMessagesHandler.processCodeTransformCancelAction(message) is IncomingCodeTransformMessage.CodeTransformStop -> inboundAppMessagesHandler.processCodeTransformStopAction(message.tabId) + is IncomingCodeTransformMessage.CodeTransformConfirmSkipTests -> inboundAppMessagesHandler.processCodeTransformConfirmSkipTests(message) is IncomingCodeTransformMessage.CodeTransformNew -> inboundAppMessagesHandler.processCodeTransformNewAction(message) is IncomingCodeTransformMessage.CodeTransformOpenTransformHub -> inboundAppMessagesHandler.processCodeTransformOpenTransformHub(message) is IncomingCodeTransformMessage.CodeTransformOpenMvnBuild -> inboundAppMessagesHandler.processCodeTransformOpenMvnBuild(message) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/InboundAppMessagesHandler.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/InboundAppMessagesHandler.kt index 4a781418cb..284a100801 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/InboundAppMessagesHandler.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/InboundAppMessagesHandler.kt @@ -15,6 +15,8 @@ interface InboundAppMessagesHandler { suspend fun processCodeTransformStopAction(tabId: String) + suspend fun processCodeTransformConfirmSkipTests(message: IncomingCodeTransformMessage.CodeTransformConfirmSkipTests) + suspend fun processCodeTransformOpenTransformHub(message: IncomingCodeTransformMessage.CodeTransformOpenTransformHub) suspend fun processCodeTransformOpenMvnBuild(message: IncomingCodeTransformMessage.CodeTransformOpenMvnBuild) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt index a0d6217dfa..c3edc72448 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt @@ -48,6 +48,13 @@ private val confirmUserSelectionButton = Button( id = CodeTransformButtonId.StartTransformation.id, ) +private val confirmSkipTestsSelectionButton = Button( + keepCardAfterClick = false, + waitMandatoryFormItems = true, + text = message("codemodernizer.chat.message.button.confirm"), + id = CodeTransformButtonId.ConfirmSkipTests.id, +) + private val openMvnBuildButton = Button( id = CodeTransformButtonId.OpenMvnBuild.id, text = message("codemodernizer.chat.message.button.view_build"), @@ -134,6 +141,22 @@ private val selectTargetVersionFormItem = FormItem( ) ) +private val selectSkipTestsFlagFormItem = FormItem( + id = CodeTransformFormItemId.SelectSkipTestsFlag.id, + title = message("codemodernizer.chat.form.user_selection.item.choose_skip_tests_option"), + mandatory = true, + options = listOf( + FormItemOption( + label = message("codemodernizer.chat.message.skip_tests_form.run_tests"), + value = message("codemodernizer.chat.message.skip_tests_form.run_tests"), + ), + FormItemOption( + label = message("codemodernizer.chat.message.skip_tests_form.skip"), + value = message("codemodernizer.chat.message.skip_tests_form.skip"), + ) + ) +) + private fun getUserSelectionFormattedMarkdown(moduleName: String): String = """ ### ${message("codemodernizer.chat.prompt.title.details")} ------------- @@ -184,11 +207,26 @@ fun buildStartNewTransformFollowup(): CodeTransformChatMessageContent = CodeTran ) ) -fun buildAuthRestoredFollowup(): CodeTransformChatMessageContent = CodeTransformChatMessageContent( - type = CodeTransformChatMessageType.FinalizedAnswer, - followUps = listOf( - startNewTransformFollowUp +fun buildUserInputSkipTestsFlagChatIntroContent(): CodeTransformChatMessageContent = + CodeTransformChatMessageContent( + message = message("codemodernizer.chat.message.skip_tests"), + type = CodeTransformChatMessageType.FinalizedAnswer, ) + +fun buildUserInputSkipTestsFlagChatContent(): CodeTransformChatMessageContent = + CodeTransformChatMessageContent( + message = message("codemodernizer.chat.form.user_selection.title"), + buttons = listOf( + confirmSkipTestsSelectionButton, + cancelUserSelectionButton, + ), + formItems = listOf(selectSkipTestsFlagFormItem), + type = CodeTransformChatMessageType.FinalizedAnswer, + ) + +fun buildUserSkipTestsFlagSelectionChatContent(skipTestsSelection: String) = CodeTransformChatMessageContent( + type = CodeTransformChatMessageType.FinalizedAnswer, + message = message("codemodernizer.chat.message.skip_tests_form.response", skipTestsSelection.lowercase()) ) fun buildUserInputChatContent(project: Project, validationResult: ValidationResult): CodeTransformChatMessageContent { diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 10a493ec45..d1295aadb2 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -55,7 +55,10 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTr import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserCancelledChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserHilSelection import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputChatContent +import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputSkipTestsFlagChatContent +import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputSkipTestsFlagChatIntroContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserSelectionSummaryChatContent +import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserSkipTestsFlagSelectionChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserStopTransformChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.messages.AuthenticationNeededExceptionMessage import software.aws.toolkits.jetbrains.services.codemodernizer.messages.CodeTransformChatMessage @@ -66,6 +69,8 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransfo import software.aws.toolkits.jetbrains.services.codemodernizer.model.CustomerSelection import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadFailureReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId +import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS +import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_SKIP_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenCopyCommandsResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenDependencyReportCommandsResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.UploadFailureReason @@ -208,26 +213,47 @@ class CodeTransformChatController( val moduleVirtualFile: VirtualFile = modulePath.toVirtualFile() as VirtualFile val moduleName = context.project.getModuleOrProjectNameForFile(moduleVirtualFile) - codeTransformChatHelper.run { - addNewMessage(buildUserSelectionSummaryChatContent(moduleName)) - addNewMessage(buildCompileLocalInProgressChatContent()) - } + codeTransformChatHelper.addNewMessage(buildUserSelectionSummaryChatContent(moduleName)) - // this should never throw the RuntimeException since invalid JDK case is already handled in previous validation step - val moduleJdkVersion = ModuleUtil.findModuleForFile(moduleVirtualFile, context.project)?.tryGetJdk(context.project) - logger.info { "Found project JDK version: ${context.project.tryGetJdk()}, module JDK version: $moduleJdkVersion. Module JDK version prioritized." } - val sourceJdk = moduleJdkVersion ?: context.project.tryGetJdk() ?: throw RuntimeException("Unable to determine source JDK version") + val sourceJdk = getSourceJdk(moduleVirtualFile) val selection = CustomerSelection( moduleVirtualFile, sourceJdk, - JavaSdkVersion.JDK_17 + JavaSdkVersion.JDK_17, ) + // Create and set a session + codeModernizerManager.createCodeModernizerSession(selection, context.project) + // Publish metric to capture user selection before local build starts telemetry.submitSelection("Confirm", selection) - codeModernizerManager.runLocalMavenBuild(context.project, selection) + codeTransformChatHelper.run { + addNewMessage(buildUserInputSkipTestsFlagChatIntroContent()) + addNewMessage(buildUserInputSkipTestsFlagChatContent()) + } + } + + override suspend fun processCodeTransformConfirmSkipTests(message: IncomingCodeTransformMessage.CodeTransformConfirmSkipTests) { + val customBuildCommand = when (message.skipTestsSelection) { + message("codemodernizer.chat.message.skip_tests_form.skip") -> MAVEN_BUILD_SKIP_UNIT_TESTS + else -> MAVEN_BUILD_RUN_UNIT_TESTS + } + codeTransformChatHelper.addNewMessage(buildUserSkipTestsFlagSelectionChatContent(message.skipTestsSelection)) + codeTransformChatHelper.addNewMessage(buildCompileLocalInProgressChatContent()) + codeModernizerManager.codeTransformationSession?.let { + it.sessionContext.customBuildCommand = customBuildCommand + codeModernizerManager.runLocalMavenBuild(context.project, it) + } + } + + private fun getSourceJdk(moduleConfigurationFile: VirtualFile): JavaSdkVersion { + // this should never throw the RuntimeException since invalid JDK case is already handled in previous validation step + val moduleJdkVersion = ModuleUtil.findModuleForFile(moduleConfigurationFile, context.project)?.tryGetJdk(context.project) + logger.info { "Found project JDK version: ${context.project.tryGetJdk()}, module JDK version: $moduleJdkVersion. Module JDK version prioritized." } + val sourceJdk = moduleJdkVersion ?: context.project.tryGetJdk() ?: error("Unable to determine source JDK version") + return sourceJdk } private suspend fun handleMavenBuildResult(mavenBuildResult: MavenCopyCommandsResult) { diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/messages/CodeTransformMessage.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/messages/CodeTransformMessage.kt index 73882308c8..0fab137e22 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/messages/CodeTransformMessage.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/messages/CodeTransformMessage.kt @@ -18,6 +18,7 @@ sealed interface CodeTransformBaseMessage : AmazonQMessage enum class CodeTransformButtonId(val id: String) { StartTransformation("codetransform-input-confirm"), CancelTransformation("codetransform-input-cancel"), + ConfirmSkipTests("codetransform-input-confirm-skip-tests"), StopTransformation("stop_transform"), OpenTransformationHub("open_transformation_hub"), OpenMvnBuild("open_mvn_build"), @@ -32,6 +33,7 @@ enum class CodeTransformButtonId(val id: String) { enum class CodeTransformFormItemId(val id: String) { SelectModule("module"), SelectTargetVersion("targetVersion"), + SelectSkipTestsFlag("skipTestsSelection"), DependencyVersion("dependencyVersion"), } @@ -81,6 +83,11 @@ sealed interface IncomingCodeTransformMessage : CodeTransformBaseMessage { @JsonProperty("tabID") val tabId: String, ) : IncomingCodeTransformMessage + data class CodeTransformConfirmSkipTests( + @JsonProperty("tabID") val tabId: String, + val skipTestsSelection: String, + ) : IncomingCodeTransformMessage + data class CodeTransformOpenMvnBuild( @JsonProperty("tabID") val tabId: String, ) : IncomingCodeTransformMessage diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 9833c2d685..913f5d8d18 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -44,6 +44,8 @@ const val ZIP_SOURCES_PATH = "sources" const val ZIP_DEPENDENCIES_PATH = "dependencies" const val BUILD_LOG_PATH = "build-logs.txt" const val MAVEN_CONFIGURATION_FILE_NAME = "pom.xml" +const val MAVEN_BUILD_RUN_UNIT_TESTS = "clean test" +const val MAVEN_BUILD_SKIP_UNIT_TESTS = "clean test-compile" const val MAVEN_DEFAULT_BUILD_DIRECTORY_NAME = "target" const val IDEA_DIRECTORY_NAME = ".idea" const val INVALID_SUFFIX_SHA = "sha1" @@ -53,6 +55,7 @@ data class CodeModernizerSessionContext( val configurationFile: VirtualFile, val sourceJavaVersion: JavaSdkVersion, val targetJavaVersion: JavaSdkVersion, + var customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS // run unit tests by default ) { private val mapper = jacksonObjectMapper() private val ignoredDependencyFileExtensions = setOf(INVALID_SUFFIX_SHA, INVALID_SUFFIX_REPOSITORIES) @@ -200,7 +203,7 @@ data class CodeModernizerSessionContext( val outputFile = createTemporaryZipFile { zip -> // 1) Manifest file val dependenciesRoot = if (depDirectory != null) "$ZIP_DEPENDENCIES_PATH/${depDirectory.name}" else null - mapper.writeValueAsString(ZipManifest(dependenciesRoot = dependenciesRoot)) + mapper.writeValueAsString(ZipManifest(dependenciesRoot = dependenciesRoot, customBuildCommand = customBuildCommand)) .byteInputStream() .use { zip.putNextEntry(Path(MANIFEST_PATH).toString(), it) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CustomerSelection.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CustomerSelection.kt index 50e0c13e2d..809e15af29 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CustomerSelection.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CustomerSelection.kt @@ -9,5 +9,5 @@ import com.intellij.openapi.vfs.VirtualFile data class CustomerSelection( val configurationFile: VirtualFile, val sourceJavaVersion: JavaSdkVersion, - val targetJavaVersion: JavaSdkVersion + val targetJavaVersion: JavaSdkVersion, ) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt index 9f9b9a6ec9..05d8791fd4 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt @@ -15,5 +15,6 @@ data class ZipManifest( val buildLogs: String = BUILD_LOG_PATH, val version: String = UPLOAD_ZIP_MANIFEST_VERSION.toString(), val hilCapabilities: List = listOf(HIL_1P_UPGRADE_CAPABILITY), - val transformCapabilities: List = listOf(EXPLAINABILITY_V1) + val transformCapabilities: List = listOf(EXPLAINABILITY_V1), + val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, ) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt index b4298c8f40..f9a0736a85 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.util.xmlb.annotations.Property import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId +import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.utils.toVirtualFile enum class JobDetails { @@ -16,6 +17,7 @@ enum class JobDetails { CONFIGURATION_FILE_PATH, TARGET_JAVA_VERSION, SOURCE_JAVA_VERSION, + CUSTOM_BUILD_COMMAND, } enum class StateFlags { @@ -29,6 +31,7 @@ fun buildState(context: CodeModernizerSessionContext, isJobOngoing: Boolean, job JobDetails.CONFIGURATION_FILE_PATH to context.configurationFile.path, JobDetails.TARGET_JAVA_VERSION to context.targetJavaVersion.description, JobDetails.SOURCE_JAVA_VERSION to context.sourceJavaVersion.description, + JobDetails.CUSTOM_BUILD_COMMAND to context.customBuildCommand ) ) flags.putAll( @@ -56,6 +59,12 @@ class CodeModernizerState : BaseState() { lastJobContext[JobDetails.SOURCE_JAVA_VERSION] ?: throw RuntimeException("Expected source language for migration path of previous job but was null") val targetJavaSdkVersion = JavaSdkVersion.fromVersionString(targetString) ?: throw RuntimeException("Invalid Java SDK version $targetString") val sourceJavaSdkVersion = JavaSdkVersion.fromVersionString(sourceString) ?: throw RuntimeException("Invalid Java SDK version $sourceString") - return CodeModernizerSessionContext(project, configurationFile, sourceJavaSdkVersion, targetJavaSdkVersion) + return CodeModernizerSessionContext( + project, + configurationFile, + sourceJavaSdkVersion, + targetJavaSdkVersion, + lastJobContext[JobDetails.CUSTOM_BUILD_COMMAND] ?: MAVEN_BUILD_RUN_UNIT_TESTS // default to running unit tests + ) } } diff --git a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt index 30fa2cc949..0d921f8b32 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt @@ -57,6 +57,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModerni import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerStartJobResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformHilDownloadArtifact +import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_SKIP_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenCopyCommandsResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.UploadFailureReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.ZipCreationResult @@ -143,7 +144,7 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa assertFalse(roots.isEmpty() || roots.size > 1) assert(rootManager.dependencies.isEmpty()) val root = roots[0] - val context = CodeModernizerSessionContext(project, root.children[0], JavaSdkVersion.JDK_1_8, JavaSdkVersion.JDK_11) + val context = CodeModernizerSessionContext(project, root.children[0], JavaSdkVersion.JDK_1_8, JavaSdkVersion.JDK_11, MAVEN_BUILD_SKIP_UNIT_TESTS) val mockFile = mock(File::class.java) val mockStringBuilder = mock(StringBuilder::class.java) val file = runInEdtAndGet { @@ -156,7 +157,10 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa numEntries += 1 val fileContent = zipFile.getInputStream(entry).bufferedReader().readLine() when (Path(entry.name)) { - Path("manifest.json") -> assertNotNull(fileContent) + Path("manifest.json") -> { + assertNotNull(fileContent) + assertTrue(fileContent.contains(MAVEN_BUILD_SKIP_UNIT_TESTS)) + } Path("sources/src/tmp.txt") -> assertEquals(fileText, fileContent) Path("build-logs.txt") -> assertNotNull(fileContent) else -> fail("Unexpected entry in zip file: $entry") diff --git a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerTestBase.kt b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerTestBase.kt index 4f40a22319..8b489b74d8 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerTestBase.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerTestBase.kt @@ -268,11 +268,10 @@ open class CodeWhispererCodeModernizerTestBase( val summaryFileMock = Mockito.mock(File::class.java) val logFileMock = Mockito.mock(File::class.java) doReturn("dummy/path").whenever(virtualFileMock).path - testSessionContextSpy = spy(CodeModernizerSessionContext(project, virtualFileMock, JavaSdkVersion.JDK_1_8, JavaSdkVersion.JDK_11)) + testSessionContextSpy = spy(CodeModernizerSessionContext(project, virtualFileMock, JavaSdkVersion.JDK_1_8, JavaSdkVersion.JDK_11, "test")) testSessionSpy = spy(CodeModernizerSession(testSessionContextSpy, 0, 0)) doNothing().whenever(testSessionSpy).deleteUploadArtifact(any()) doReturn(Job()).whenever(codeModernizerManagerSpy).launchModernizationJob(any(), any()) - doReturn(testSessionSpy).whenever(codeModernizerManagerSpy).createCodeModernizerSession(any(), any()) testCodeModernizerArtifact = spy( CodeModernizerArtifact( diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/codeTransformChatConnector.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/codeTransformChatConnector.ts index 1108e061da..7038291881 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/codeTransformChatConnector.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/codeTransformChatConnector.ts @@ -225,6 +225,13 @@ export class CodeTransformChatConnector { tabID, tabType: 'codetransform', }) + } else if (action.id === FormButtonIds.CodeTransformInputSkipTests) { + this.sendMessageToExtension({ + command: 'codetransform-confirm-skip-tests', + tabID, + tabType: 'codetransform', + skipTestsSelection: action.formItemValues?.skipTestsSelection + }) } else if (action.id === FormButtonIds.OpenTransformationHub) { this.sendMessageToExtension({ command: 'codetransform-open-transform-hub', diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/commands.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/commands.ts index 53e9089710..c1405a1a6e 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/commands.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/commands.ts @@ -32,6 +32,7 @@ type MessageCommand = | 'codetransform-start' | 'codetransform-cancel' | 'codetransform-stop' + | 'codetransform-confirm-skip-tests' | 'codetransform-new' | 'codetransform-open-transform-hub' | 'codetransform-open-mvn-build' diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/forms/constants.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/forms/constants.ts index 0d319cda92..c81ed0a36e 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/forms/constants.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/forms/constants.ts @@ -6,6 +6,7 @@ export const enum FormButtonIds { CodeTransformInputConfirm = 'codetransform-input-confirm', CodeTransformInputCancel = 'codetransform-input-cancel', + CodeTransformInputSkipTests = 'codetransform-input-confirm-skip-tests', OpenMvnBuild = 'open_mvn_build', StopTransform = 'stop_transform', OpenTransformationHub = 'open_transformation_hub', @@ -21,6 +22,7 @@ export const isFormButtonCodeTransform = (id: string): boolean => { return ( id === FormButtonIds.CodeTransformInputConfirm || id === FormButtonIds.CodeTransformInputCancel || + id === FormButtonIds.CodeTransformInputSkipTests || id === FormButtonIds.CodeTransformViewDiff || id === FormButtonIds.CodeTransformViewSummary || id === FormButtonIds.CodeTransformViewBuildLog || diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 15e5242b86..867cf7178b 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -553,6 +553,7 @@ code.aws.workspaces=Amazon CodeCatalyst code.aws.workspaces.short=Dev Environments codemodernizer.builderrordialog.description.title=Error occurred when building your project codemodernizer.chat.form.user_selection.item.choose_module=Choose a module to transform +codemodernizer.chat.form.user_selection.item.choose_skip_tests_option=Choose to skip unit tests codemodernizer.chat.form.user_selection.item.choose_target_version=Choose the target code version codemodernizer.chat.form.user_selection.title=Q - Code transformation codemodernizer.chat.message.absolute_path_detected=I detected {0} potential absolute file path(s) in your {1} file: **{2}**. Absolute file paths might cause issues when I build your code. Any errors will show up in the build log. @@ -595,7 +596,7 @@ codemodernizer.chat.message.hil.trying_resume=Trying to resume transformation wi codemodernizer.chat.message.hil.user_rejected=I'll continue upgrading your module. When I'm done, you can review the dependency error in the Transformation summary. codemodernizer.chat.message.local_build_begin=I'm building your module. This can take up to 10 minutes, depending on the size of your module. codemodernizer.chat.message.local_build_failed=Sorry, I couldn't run the Maven clean install command to build your module. -codemodernizer.chat.message.local_build_success=I was able to build your project and will start uploading your code. +codemodernizer.chat.message.local_build_success=I was able to build your module and will start uploading your code. codemodernizer.chat.message.result.fail=Sorry, I ran into an issue during the transformation. Please try again. codemodernizer.chat.message.result.fail_initial_build=I am having trouble building your project in the secure build environment and couldn't complete the transformation. codemodernizer.chat.message.result.fail_initial_build_no_build_log=I am having trouble building your project in the secure build environment: {0}. @@ -604,6 +605,10 @@ codemodernizer.chat.message.result.partially_success=I upgraded part of your cod codemodernizer.chat.message.result.success=I successfully upgraded your code to Java 17. You can review the diff to see my proposed changes and accept or reject them. The transformation summary has details about the files I updated. codemodernizer.chat.message.result.zip_too_large=Sorry, your project size exceeds the Amazon Q Code Transformation upload limit of 2GB. codemodernizer.chat.message.resume_ongoing=I'm still transforming your code. It can take 10 to 30 minutes to upgrade your code, depending on the size of your module. To monitor progress, go to the Transformation Hub. +codemodernizer.chat.message.skip_tests=I will build your module using `mvn test` by default. If you would like me to build your module without running unit tests, I will use `mvn test-compile`. +codemodernizer.chat.message.skip_tests_form.response=Okay, I will {0} when building your module. +codemodernizer.chat.message.skip_tests_form.run_tests=Run unit tests +codemodernizer.chat.message.skip_tests_form.skip=Skip unit tests codemodernizer.chat.message.transform_begin=I'm starting to transform your code. It can take 10 to 30 minutes to upgrade your code, depending on the size of your module. To monitor progress, go to the Transformation Hub. codemodernizer.chat.message.transform_cancelled_by_user=I cancelled your transformation. If you want to start another transformation, choose **Start a new transformation**. codemodernizer.chat.message.transform_in_progress=If I run into any issues, I might pause the transformation to get input from you on how to proceed. @@ -615,12 +620,12 @@ codemodernizer.chat.message.upload_failed_other=Sorry, I was unable to upload yo codemodernizer.chat.message.upload_failed_ssl_error=Sorry, I was unable to upload your project. This might have been caused by your IDE not trusting the certificate of your HTTP proxy. Ensure all certificates for your proxy client have been configured in your IDE, and then retry transformation. codemodernizer.chat.message.upload_failed_url_expired=Sorry, I couldn't upload your project to begin the transformation. The Amazon S3 pre-signed URL used to upload your code expired after 30 minutes. This might have been caused by delays introduced by intermediate services in your network infrastructure.\n\nCheck your network configuration for services that might be causing delays. If the issue persists, you might need to allow list the following Amazon S3 bucket: 'amazonq-code-transformation-us-east-1-c6160f047e0.s3.amazonaws.com'. codemodernizer.chat.message.validation.check_eligible_projects=I'm checking for open projects that are eligible for Code Transformation. -codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and the correct language level. In the Modules tab, set the correct module JDK and the correct language level. +codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level. codemodernizer.chat.message.validation.error.more_info=For more information, see the [Amazon Q documentation]({0}). codemodernizer.chat.message.validation.error.no_pom=Sorry, I couldn't find a module that I can upgrade. I couldn't find a pom.xml file in any of your open projects. Currently, I can only upgrade Java 8 or Java 11 projects built on Maven. -codemodernizer.chat.message.validation.error.other=Sorry, I couldn't find a module that I can upgrade. Currently, I can only upgrade Java 8 or Java 11 projects built on Maven. If you have a Java 8 or Java 11 module in your workspace, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and the correct language level. In the Modules tab, set the correct module JDK and the correct language level. -codemodernizer.chat.message.validation.error.unsupported_java_version=Sorry, I couldn't find a module that I can upgrade. Currently, I can only upgrade Java 8 or Java 11 modules built on Maven. If you have a Java 8 or Java 11 module in your workspace, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and the correct language level. In the Modules tab, set the correct module JDK and the correct language level. -codemodernizer.chat.message.validation.no_jdk=I couldn't build your project with your current JDK configuration. To update your JDK, go to File and choose Project Structure. In the Projects tab, set the correct project JDK in the SDK field. In the Modules tab, set the correct module JDK in the SDK field. +codemodernizer.chat.message.validation.error.other=Sorry, I couldn't find a module that I can upgrade. Currently, I can only upgrade Java 8 or Java 11 projects built on Maven. If you have a Java 8 or Java 11 module in your workspace, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and the correct language level. In the Modules tab, set the correct module JDK and language level. +codemodernizer.chat.message.validation.error.unsupported_java_version=Sorry, I couldn't find a module that I can upgrade. Currently, I can only upgrade Java 8 or Java 11 modules built on Maven. If you have a Java 8 or Java 11 module in your workspace, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and the correct language level. In the Modules tab, set the correct module JDK and language level. +codemodernizer.chat.message.validation.no_jdk=I couldn't build your project with your current JDK configuration. To update your JDK, go to File and choose Project Structure. In the Projects tab, set the correct project JDK in the SDK field. In the Modules tab, set the correct module JDK in the SDK field. In Maven Runner settings, set the correct JDK in the JRE field. codemodernizer.chat.prompt.label.dependency_current_version=Current version codemodernizer.chat.prompt.label.dependency_name=Dependency name codemodernizer.chat.prompt.label.dependency_selected_version=Target version