Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
629a053
initial attempt at showing multiple diff patches, need to sync chat w…
ntarakad-aws Nov 3, 2024
6ef2c1a
adding support for different json format
ntarakad-aws Nov 6, 2024
853b40c
adding new UI messaging for patch descriptions and removing redundant…
ntarakad-aws Nov 14, 2024
0429617
added in forms for one or multiple diffs and made manifest changes ac…
ntarakad-aws Nov 15, 2024
5f7c508
removing old multiple patches description
ntarakad-aws Nov 15, 2024
80e5b8f
fixing patch descriptions message
ntarakad-aws Nov 16, 2024
9b6c1d4
fixed issue with undefined in changes applied message and addressing …
ntarakad-aws Nov 17, 2024
61b088b
updated messaging for one or multiple diffs when job success/partial …
ntarakad-aws Nov 18, 2024
f89c49f
fixing one diff and off by one error for multiple diffs and addressin…
ntarakad-aws Nov 18, 2024
7c961ba
added unit tests and fixing off by one logic and detekt errors
ntarakad-aws Nov 18, 2024
89a8bb5
adding test zip
ntarakad-aws Nov 18, 2024
a667cc4
removing sample diff zip
ntarakad-aws Nov 18, 2024
1a1fdb8
adding sample diff zip
ntarakad-aws Nov 18, 2024
77fb5b9
adding simple back
ntarakad-aws Nov 18, 2024
f5bef5e
Merge branch 'main' into selective-transform
ntarakad-aws Nov 18, 2024
f2ff3d4
fixing detekt and adding patch applied notification and updating unit…
ntarakad-aws Nov 19, 2024
b07c148
addressing comments on PR, detekt issues, and adding feature flag
ntarakad-aws Nov 19, 2024
14992ff
adding feature flag and telemetry
ntarakad-aws Nov 20, 2024
6fb6f3f
fixing telemetry and readValue
ntarakad-aws Nov 20, 2024
98c9eab
fixing failed test and lint
ntarakad-aws Nov 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,35 @@ import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.exists
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.info
import software.aws.toolkits.jetbrains.core.coroutines.EDT
import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineBgContext
import software.aws.toolkits.jetbrains.core.coroutines.projectCoroutineScope
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.NoTokenInitializedException
import software.aws.toolkits.jetbrains.services.amazonq.CODE_TRANSFORM_TROUBLESHOOT_DOC_DOWNLOAD_ERROR_OVERVIEW
import software.aws.toolkits.jetbrains.services.amazonq.CODE_TRANSFORM_TROUBLESHOOT_DOC_DOWNLOAD_EXPIRED
import software.aws.toolkits.jetbrains.services.codemodernizer.client.GumbyClient
import software.aws.toolkits.jetbrains.services.codemodernizer.commands.CodeTransformMessageListener
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildStartNewTransformFollowup
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.createViewDiffButton
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.getDownloadedArtifactTextFromType
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.viewSummaryButton
import software.aws.toolkits.jetbrains.services.codemodernizer.controller.CodeTransformChatHelper
import software.aws.toolkits.jetbrains.services.codemodernizer.messages.CodeTransformChatMessageContent
import software.aws.toolkits.jetbrains.services.codemodernizer.messages.CodeTransformChatMessageType
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerArtifact
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformFailureBuildLog
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformHilDownloadArtifact
import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadArtifactResult
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.ParseZipFailureReason
import software.aws.toolkits.jetbrains.services.codemodernizer.model.PatchInfo
import software.aws.toolkits.jetbrains.services.codemodernizer.model.UnzipFailureReason
import software.aws.toolkits.jetbrains.services.codemodernizer.state.CodeModernizerSessionState
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilArtifactDir
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.isValidCodeTransformConnection
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.openTroubleshootingGuideNotificationAction
import software.aws.toolkits.jetbrains.utils.notifyInfo
import software.aws.toolkits.jetbrains.utils.notifyStickyInfo
import software.aws.toolkits.jetbrains.utils.notifyStickyWarn
import software.aws.toolkits.resources.message
Expand All @@ -57,20 +66,44 @@ import java.util.concurrent.atomic.AtomicBoolean
const val DOWNLOAD_PROXY_WILDCARD_ERROR: String = "Dangling meta character '*' near index 0"
const val DOWNLOAD_SSL_HANDSHAKE_ERROR: String = "Unable to execute HTTP request: javax.net.ssl.SSLHandshakeException"
const val INVALID_ARTIFACT_ERROR: String = "Invalid artifact"

class ArtifactHandler(private val project: Project, private val clientAdaptor: GumbyClient) {
val patchDescriptions = mapOf(
"Prepare minimal upgrade to Java 17" to "This diff patch covers the set of upgrades for Springboot, JUnit, and PowerMockito frameworks.",
"Popular Enterprise Specifications and Application Frameworks upgrade" to "This diff patch covers the set of upgrades for Jakarta EE 10, Hibernate 6.2, " +
"and Micronaut 3.",
"HTTP Client Utilities, Apache Commons Utilities, and Web Frameworks" to "This diff patch covers the set of upgrades for Apache HTTP Client 5, Apache " +
"Commons utilities (Collections, IO, Lang, Math), Struts 6.0.",
"Testing Tools and Frameworks upgrade" to "This diff patch covers the set of upgrades for ArchUnit, Mockito, TestContainers, Cucumber, and additionally, " +
"Jenkins plugins and the Maven Wrapper.",
"Miscellaneous Processing Documentation upgrade" to "This diff patch covers a diverse set of upgrades spanning ORMs, XML processing, API documentation, " +
"and more.",
"Deprecated API replacement and dependency upgrades" to "This diff patch replaces deprecated APIs and makes additional dependency version upgrades."
)

class ArtifactHandler(
private val project: Project,
private val clientAdaptor: GumbyClient,
private val codeTransformChatHelper: CodeTransformChatHelper? = null,
) {
private val telemetry = CodeTransformTelemetryManager.getInstance(project)
private val downloadedArtifacts = mutableMapOf<JobId, Path>()
private val downloadedSummaries = mutableMapOf<JobId, TransformationSummary>()
private val downloadedBuildLogPath = mutableMapOf<JobId, Path>()
private var isCurrentlyDownloading = AtomicBoolean(false)
private var totalPatchFiles: Int = 0
private var sharedPatchIndex: Int = 0

internal suspend fun displayDiff(job: JobId, source: CodeTransformVCSViewerSrcComponents) {
if (isCurrentlyDownloading.get()) return
when (val result = downloadArtifact(job, TransformationDownloadArtifactType.CLIENT_INSTRUCTIONS)) {
is DownloadArtifactResult.Success -> {
if (result.artifact !is CodeModernizerArtifact) return notifyUnableToApplyPatch("")
displayDiffUsingPatch(result.artifact.patch, job, source)
totalPatchFiles = result.artifact.patches.size
if (result.artifact.description == null) {
displayDiffUsingPatch(result.artifact.patches.first(), totalPatchFiles, null, job, source)
} else {
val diffDescription = result.artifact.description[getCurrentPatchIndex()]
displayDiffUsingPatch(result.artifact.patches[getCurrentPatchIndex()], totalPatchFiles, diffDescription, job, source)
}
}
is DownloadArtifactResult.ParseZipFailure -> notifyUnableToApplyPatch(result.failureReason.errorMessage)
is DownloadArtifactResult.UnzipFailure -> notifyUnableToApplyPatch(result.failureReason.errorMessage)
Expand Down Expand Up @@ -246,8 +279,14 @@ class ArtifactHandler(private val project: Project, private val clientAdaptor: G
/**
* Opens the built-in patch dialog to display the diff and allowing users to apply the changes locally.
*/
internal fun displayDiffUsingPatch(patchFile: VirtualFile, jobId: JobId, source: CodeTransformVCSViewerSrcComponents) {
runInEdt {
internal suspend fun displayDiffUsingPatch(
patchFile: VirtualFile,
totalPatchFiles: Int,
diffDescription: PatchInfo?,
jobId: JobId,
source: CodeTransformVCSViewerSrcComponents,
) {
withContext(EDT) {
val dialog = ApplyPatchDifferentiatedDialog(
project,
ApplyPatchDefaultExecutor(project),
Expand All @@ -256,7 +295,14 @@ class ArtifactHandler(private val project: Project, private val clientAdaptor: G
patchFile,
null,
ChangeListManager.getInstance(project)
.addChangeList(message("codemodernizer.patch.name"), ""),
.addChangeList(
if (diffDescription != null) {
"${diffDescription.name} (${if (diffDescription.isSuccessful) "Success" else "Failure"})"
} else {
patchFile.name
},
""
),
null,
null,
null,
Expand All @@ -265,7 +311,44 @@ class ArtifactHandler(private val project: Project, private val clientAdaptor: G
dialog.isModal = true

if (dialog.showAndGet()) {
telemetry.submitSelection("Submit-${patchDescriptions[diffDescription?.name]}")
telemetry.viewArtifact(CodeTransformArtifactType.ClientInstructions, jobId, "Submit", source)
if (diffDescription == null) {
val resultContent = CodeTransformChatMessageContent(
type = CodeTransformChatMessageType.PendingAnswer,
message = message("codemodernizer.chat.message.changes_applied"),
)
codeTransformChatHelper?.updateLastPendingMessage(resultContent)
codeTransformChatHelper?.addNewMessage(buildStartNewTransformFollowup())
} else {
if (getCurrentPatchIndex() < totalPatchFiles) {
val message = "I applied the changes in diff patch ${getCurrentPatchIndex() + 1} of $totalPatchFiles. " +
"${patchDescriptions[diffDescription.name]}"
val notificationMessage = "Amazon Q applied the changes in diff patch ${getCurrentPatchIndex() + 1} of $totalPatchFiles " +
"to your project."
val notificationTitle = "Diff patch ${getCurrentPatchIndex() + 1} of $totalPatchFiles applied"
setCurrentPatchIndex(getCurrentPatchIndex() + 1)
notifyInfo(notificationTitle, notificationMessage, project)
if (getCurrentPatchIndex() == totalPatchFiles) {
codeTransformChatHelper?.updateLastPendingMessage(
CodeTransformChatMessageContent(type = CodeTransformChatMessageType.PendingAnswer, message = message)
)
} else {
codeTransformChatHelper?.updateLastPendingMessage(
CodeTransformChatMessageContent(
type = CodeTransformChatMessageType.PendingAnswer,
message = message,
buttons = listOf(
createViewDiffButton("View diff ${getCurrentPatchIndex() + 1}/$totalPatchFiles"),
viewSummaryButton
)
)
)
}
} else {
codeTransformChatHelper?.addNewMessage(buildStartNewTransformFollowup())
}
}
} else {
telemetry.viewArtifact(CodeTransformArtifactType.ClientInstructions, jobId, "Cancel", source)
}
Expand Down Expand Up @@ -388,6 +471,12 @@ class ArtifactHandler(private val project: Project, private val clientAdaptor: G

fun getSummary(job: JobId) = downloadedSummaries[job]

private fun getCurrentPatchIndex() = sharedPatchIndex

private fun setCurrentPatchIndex(index: Int) {
sharedPatchIndex = index
}

private fun showSummaryFromFile(summaryFile: File) {
val summaryMarkdownVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(summaryFile)
if (summaryMarkdownVirtualFile != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,12 +576,6 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo
resumeJob(session, lastJobId, currentJobResult)
}

private fun displayDiffNotificationAction(jobId: JobId): NotificationAction = NotificationAction.createSimple(
message("codemodernizer.notification.info.modernize_complete.view_diff")
) {
artifactHandler.displayDiffAction(jobId, CodeTransformVCSViewerSrcComponents.ToastNotification)
}

private fun displaySummaryNotificationAction(jobId: JobId) =
NotificationAction.createSimple(message("codemodernizer.notification.info.modernize_complete.view_summary")) {
artifactHandler.showTransformationSummary(jobId)
Expand Down Expand Up @@ -638,7 +632,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo
message("codemodernizer.notification.info.modernize_partial_complete.title"),
message("codemodernizer.notification.info.modernize_partial_complete.content", result.targetJavaVersion.description),
project,
listOf(displayDiffNotificationAction(result.jobId), displaySummaryNotificationAction(result.jobId), displayFeedbackNotificationAction()),
listOf(displaySummaryNotificationAction(result.jobId), displayFeedbackNotificationAction()),
)
jobId = result.jobId
}
Expand All @@ -648,7 +642,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo
message("codemodernizer.notification.info.modernize_complete.title"),
message("codemodernizer.notification.info.modernize_complete.content"),
project,
listOf(displayDiffNotificationAction(result.jobId), displaySummaryNotificationAction(result.jobId)),
listOf(displaySummaryNotificationAction(result.jobId)),
)
jobId = result.jobId
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ import java.util.concurrent.atomic.AtomicBoolean
import javax.net.ssl.SSLHandshakeException

const val MAX_ZIP_SIZE = 2000000000 // 2GB
const val EXPLAINABILITY_V1 = "EXPLAINABILITY_V1"
const val SELECTIVE_TRANSFORMATION_V1 = "SELECTIVE_TRANSFORMATION_V1"

// constants for handling SDKClientException
const val CONNECTION_REFUSED_ERROR: String = "Connection refused"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ private enum class CodeTransformMessageTypes(val type: String) {
CodeTransformStop("codetransform-stop"),
CodeTransformCancel("codetransform-cancel"),
CodeTransformConfirmSkipTests("codetransform-confirm-skip-tests"),
CodeTransformConfirmOneOrMultipleDiffs("codetransform-confirm-one-or-multiple-diffs"),
CodeTransformNew("codetransform-new"),
CodeTransformOpenTransformHub("codetransform-open-transform-hub"),
CodeTransformOpenMvnBuild("codetransform-open-mvn-build"),
Expand Down Expand Up @@ -72,6 +73,7 @@ class CodeTransformChatApp : AmazonQApp {
CodeTransformMessageTypes.CodeTransformCancel.type to IncomingCodeTransformMessage.CodeTransformCancel::class,
CodeTransformMessageTypes.ChatPrompt.type to IncomingCodeTransformMessage.ChatPrompt::class,
CodeTransformMessageTypes.CodeTransformConfirmSkipTests.type to IncomingCodeTransformMessage.CodeTransformConfirmSkipTests::class,
CodeTransformMessageTypes.CodeTransformConfirmOneOrMultipleDiffs.type to IncomingCodeTransformMessage.CodeTransformConfirmOneOrMultipleDiffs::class,
CodeTransformMessageTypes.CodeTransformNew.type to IncomingCodeTransformMessage.CodeTransformNew::class,
CodeTransformMessageTypes.CodeTransformOpenTransformHub.type to IncomingCodeTransformMessage.CodeTransformOpenTransformHub::class,
CodeTransformMessageTypes.CodeTransformOpenMvnBuild.type to IncomingCodeTransformMessage.CodeTransformOpenMvnBuild::class,
Expand Down Expand Up @@ -166,6 +168,7 @@ class CodeTransformChatApp : AmazonQApp {
is IncomingCodeTransformMessage.CodeTransformStop -> inboundAppMessagesHandler.processCodeTransformStopAction(message.tabId)
is IncomingCodeTransformMessage.ChatPrompt -> inboundAppMessagesHandler.processChatPromptMessage(message)
is IncomingCodeTransformMessage.CodeTransformConfirmSkipTests -> inboundAppMessagesHandler.processCodeTransformConfirmSkipTests(message)
is IncomingCodeTransformMessage.CodeTransformConfirmOneOrMultipleDiffs -> inboundAppMessagesHandler.processCodeTransformOneOrMultipleDiffs(message)
is IncomingCodeTransformMessage.CodeTransformNew -> inboundAppMessagesHandler.processCodeTransformNewAction(message)
is IncomingCodeTransformMessage.CodeTransformOpenTransformHub -> inboundAppMessagesHandler.processCodeTransformOpenTransformHub(message)
is IncomingCodeTransformMessage.CodeTransformOpenMvnBuild -> inboundAppMessagesHandler.processCodeTransformOpenMvnBuild(message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ interface InboundAppMessagesHandler {

suspend fun processCodeTransformConfirmSkipTests(message: IncomingCodeTransformMessage.CodeTransformConfirmSkipTests)

suspend fun processCodeTransformOneOrMultipleDiffs(message: IncomingCodeTransformMessage.CodeTransformConfirmOneOrMultipleDiffs)

suspend fun processCodeTransformOpenTransformHub(message: IncomingCodeTransformMessage.CodeTransformOpenTransformHub)

suspend fun processCodeTransformOpenMvnBuild(message: IncomingCodeTransformMessage.CodeTransformOpenMvnBuild)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ class GumbyClient(private val project: Project) {
it.timestamp(Instant.now())
it.ideCategory(IdeCategory.JETBRAINS)
it.programmingLanguage { language ->
language.languageName(metrics.programmingLanguage)
language.languageName(metrics.programmingLanguage?.lowercase())
}
it.linesOfCodeChanged(metrics.linesOfCodeChanged)
it.charsOfCodeChanged(metrics.charactersOfCodeChanged)
Expand Down
Loading
Loading