Skip to content

Commit

Permalink
Merge remote-tracking branch 'andrewyuq/cw-telemetry'
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewyuq committed Oct 4, 2024
2 parents 34b3435 + 6370f4b commit cc2583d
Show file tree
Hide file tree
Showing 41 changed files with 726 additions and 476 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ fun Project.buildMetadata() =
} catch(e: Exception) {
logger.warn("Could not determine current commit", e)

"unknownCommit"
"beta.20240910"
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

# Toolkit Version
toolkitVersion=3.31-SNAPSHOT
toolkitVersion=99.99.2

# Publish Settings
publishToken=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="migration.software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator"
serviceImplementation="software.aws.toolkits.jetbrains.services.codewhisperer.customization.DefaultCodeWhispererModelConfigurator"/>
<applicationService overrides="true" serviceInterface="com.intellij.ide.plugins.PluginManagementPolicy"
serviceImplementation="software.aws.toolkits.jetbrains.services.codewhisperer.plugin.QBetaPluginManagementPolicy"/>

<projectService serviceInterface="software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor"
serviceImplementation="software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptorImpl"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.DumbAware
import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer.actions

import com.intellij.icons.AllIcons
import com.intellij.ide.plugins.marketplace.MarketplaceRequests
import com.intellij.notification.NotificationAction
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.updateSettings.impl.PluginDownloader
import com.intellij.openapi.updateSettings.impl.UpdateSettings
import software.aws.toolkits.jetbrains.AwsToolkit
import software.aws.toolkits.jetbrains.core.plugin.PluginUpdateManager
import software.aws.toolkits.jetbrains.utils.notifyInfo
import software.aws.toolkits.resources.AwsCoreBundle
import software.aws.toolkits.resources.message

class QSwitchToMarketplaceVersionAction :
AnAction(
message("codewhisperer.actions.switch_to_marketplace.title"),
null,
AllIcons.Actions.Refresh
),
DumbAware {

override fun getActionUpdateThread() = ActionUpdateThread.BGT

override fun update(e: AnActionEvent) {
e.project?.let {
e.presentation.isEnabledAndVisible = PluginUpdateManager.getInstance().isBeta()
}
}

override fun actionPerformed(e: AnActionEvent) {
UpdateSettings.getInstance().storedPluginHosts.remove(CUSTOM_PLUGIN_URL)
UpdateSettings.getInstance().storedPluginHosts.remove("$CUSTOM_PLUGIN_URL/")

runInEdt {
ProgressManager.getInstance().run(object : Task.Backgroundable(
null,
message("codewhisperer.actions.switch_to_marketplace.progress.title"),
true
) {
override fun run(indicator: ProgressIndicator) {
installMarketplaceAwsPlugins(PluginId.getId(AwsToolkit.CORE_PLUGIN_ID), indicator)
installMarketplaceAwsPlugins(PluginId.getId(AwsToolkit.Q_PLUGIN_ID), indicator)
}
})
}
}

private fun installMarketplaceAwsPlugins(pluginId: PluginId, indicator: ProgressIndicator) {
// force update to marketplace version
try {
// MarketplaceRequest class is marked as @ApiStatus.Internal
val descriptor = MarketplaceRequests.loadLastCompatiblePluginDescriptors(setOf(pluginId))
.find { it.pluginId == pluginId } ?: return

val downloader = PluginDownloader.createDownloader(descriptor)
if (!downloader.prepareToInstall(indicator)) return
downloader.install()

if (pluginId == PluginId.getId(AwsToolkit.CORE_PLUGIN_ID)) return
notifyInfo(
title = AwsCoreBundle.message("aws.notification.auto_update.title", "Amazon Q"),
content = AwsCoreBundle.message("aws.settings.auto_update.notification.message"),
project = null,
notificationActions = listOf(
NotificationAction.createSimpleExpiring(AwsCoreBundle.message("aws.settings.auto_update.notification.yes")) {
ApplicationManager.getApplication().restart()
},
NotificationAction.createSimpleExpiring(AwsCoreBundle.message("aws.settings.auto_update.notification.no")) {
}
)
)
} catch (e: Exception) {
return
}
return
}

companion object {
private const val CUSTOM_PLUGIN_URL = "https://d244q0w8umigth.cloudfront.net"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@ import com.intellij.codeInsight.editorActions.TypedHandlerDelegate
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import kotlinx.coroutines.Job
import software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererEditorUtil.shouldSkipInvokingBasedOnRightContext
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererAutoTriggerService
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererAutomatedTriggerType
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants

class CodeWhispererTypedHandler : TypedHandlerDelegate() {
private var triggerOnIdle: Job? = null
override fun charTyped(c: Char, project: Project, editor: Editor, psiFiles: PsiFile): Result {
triggerOnIdle?.cancel()

if (shouldSkipInvokingBasedOnRightContext(editor)
) {
if (shouldSkipInvokingBasedOnRightContext(editor)) {
return Result.CONTINUE
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.actions.SsoLogoutAction
import software.aws.toolkits.jetbrains.core.credentials.pinning.CodeWhispererConnection
import software.aws.toolkits.jetbrains.core.plugin.PluginUpdateManager
import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererConnectOnGithubAction
import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererLearnMoreAction
import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererProvideFeedbackAction
import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererShowSettingsAction
import software.aws.toolkits.jetbrains.services.codewhisperer.actions.QSwitchToMarketplaceVersionAction
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.ActionProvider
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.Customize
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.Learn
Expand All @@ -24,6 +26,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.P
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.PauseCodeScans
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.Resume
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.ResumeCodeScans
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.buildActionListForBeta
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.buildActionListForCodeScan
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.buildActionListForConnectHelp
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.actions.buildActionListForInlineSuggestions
Expand All @@ -45,6 +48,7 @@ class QStatusBarLoggedInActionGroup : DefaultActionGroup() {
override val sendFeedback = CodeWhispererProvideFeedbackAction()
override val connectOnGithub = CodeWhispererConnectOnGithubAction()
override val documentation = CodeWhispererLearnMoreAction()
override val switchToMarketplace = QSwitchToMarketplaceVersionAction()
}

override fun getChildren(e: AnActionEvent?) = e?.project?.let {
Expand All @@ -65,6 +69,12 @@ class QStatusBarLoggedInActionGroup : DefaultActionGroup() {
add(Separator.create(message("codewhisperer.statusbar.sub_menu.connect_help.title")))
addAll(buildActionListForConnectHelp(actionProvider))

if (PluginUpdateManager.getInstance().isBeta()) {
add(Separator.create())
add(Separator.create("Beta"))
addAll(buildActionListForBeta(actionProvider))
}

add(Separator.create())
add(CodeWhispererShowSettingsAction())
ToolkitConnectionManager.getInstance(it).activeConnectionForFeature(CodeWhispererConnection.getInstance())?.let { c ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ interface ActionProvider<T> {
val sendFeedback: T
val connectOnGithub: T
val documentation: T
val switchToMarketplace: T
}

@SuppressWarnings("UnusedParameter")
Expand Down Expand Up @@ -84,3 +85,8 @@ fun <T> buildActionListForConnectHelp(actionProvider: ActionProvider<T>): List<T
add(actionProvider.connectOnGithub)
add(actionProvider.documentation)
}

fun <T> buildActionListForBeta(actionProvider: ActionProvider<T>): List<T> =
buildList {
add(actionProvider.switchToMarketplace)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ import software.amazon.awssdk.services.codewhispererruntime.model.GenerateComple
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.sessionconfig.PayloadContext
import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererAutomatedTriggerType
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererIntelliSenseOnHoverListener
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.services.codewhisperer.service.RequestContext
import software.aws.toolkits.jetbrains.services.codewhisperer.service.ResponseContext
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.setIntelliSensePopupAlpha
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CrossFileStrategy
import software.aws.toolkits.jetbrains.services.codewhisperer.util.SupplementalContextStrategy
import software.aws.toolkits.jetbrains.services.codewhisperer.util.UtgStrategy
Expand Down Expand Up @@ -130,6 +134,16 @@ data class SessionContext(
var hasAccepted: Boolean = false
) : Disposable {
private var isDisposed = false
init {
project.messageBus.connect().subscribe(
CodeWhispererService.CODEWHISPERER_INTELLISENSE_POPUP_ON_HOVER,
object : CodeWhispererIntelliSenseOnHoverListener {
override fun onEnter() {
CodeWhispererPopupManager.getInstance().bringSuggestionInlayToFront(editor, popup, opposite = true)
}
}
)
}

@RequiresEdt
override fun dispose() {
Expand All @@ -138,6 +152,7 @@ data class SessionContext(
hasAccepted,
CodeWhispererInvocationStatus.getInstance().popupStartTimestamp?.let { Duration.between(it, Instant.now()) }
)
setIntelliSensePopupAlpha(editor, 0f)
CodeWhispererInvocationStatus.getInstance().setDisplaySessionActive(false)

if (hasAccepted) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer.plugin

import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.PluginManagementPolicy
import com.intellij.ide.plugins.org.PluginManagerFilters

// Specifically for "Switch Back to Marketplace" action because the default one doesn't support downgrade
class QBetaPluginManagementPolicy : PluginManagementPolicy {
override fun canEnablePlugin(descriptor: IdeaPluginDescriptor?): Boolean =
descriptor?.let { PluginManagerFilters.getInstance().allowInstallingPlugin(it) } ?: true

override fun canInstallPlugin(descriptor: IdeaPluginDescriptor?): Boolean = canEnablePlugin(descriptor)

override fun isDowngradeAllowed(localDescriptor: IdeaPluginDescriptor?, remoteDescriptor: IdeaPluginDescriptor?): Boolean = true

override fun isInstallFromDiskAllowed(): Boolean = PluginManagerFilters.getInstance().allowInstallFromDisk()

override fun isUpgradeAllowed(localDescriptor: IdeaPluginDescriptor?, remoteDescriptor: IdeaPluginDescriptor?): Boolean = true
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@

package software.aws.toolkits.jetbrains.services.codewhisperer.popup

import com.intellij.codeInsight.hint.ParameterInfoController
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.idea.AppMode
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_BACKSPACE
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_ENTER
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_ESCAPE
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_TAB
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.components.Service
Expand All @@ -29,6 +25,8 @@ import com.intellij.openapi.editor.event.CaretEvent
import com.intellij.openapi.editor.event.CaretListener
import com.intellij.openapi.editor.event.DocumentEvent
import com.intellij.openapi.editor.event.DocumentListener
import com.intellij.openapi.editor.event.EditorMouseEvent
import com.intellij.openapi.editor.event.EditorMouseMotionListener
import com.intellij.openapi.editor.event.SelectionEvent
import com.intellij.openapi.editor.event.SelectionListener
import com.intellij.openapi.project.Project
Expand Down Expand Up @@ -62,7 +60,10 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.Cod
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupBackspaceHandler
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupEnterHandler
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupEscHandler
<<<<<<< HEAD
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupTabHandler
=======
>>>>>>> andrewyuq/cw-telemetry
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupTypedHandler
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererAcceptButtonActionListener
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererActionListener
Expand All @@ -71,7 +72,6 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.Co
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererScrollListener
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererColorUtil.POPUP_DIM_HEX
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.POPUP_INFO_TEXT_SIZE
Expand Down Expand Up @@ -306,6 +306,20 @@ class CodeWhispererPopupManager {
popup.showInBestPositionFor(editor)
}
}

bringSuggestionInlayToFront(editor, popup, !force)
}

fun bringSuggestionInlayToFront(editor: Editor, popup: JBPopup?, opposite: Boolean = false) {
val qInlinePopupAlpha = if (opposite) 1f else 0.1f
val intelliSensePopupAlpha = if (opposite) 0f else 0.8f

(popup as AbstractPopup?)?.popupWindow?.let {
WindowManager.getInstance().setAlphaModeRatio(it, qInlinePopupAlpha)
}
ComponentUtil.getWindow(LookupManager.getActiveLookup(editor)?.component)?.let {
WindowManager.getInstance().setAlphaModeRatio(it, intelliSensePopupAlpha)
}
}

fun initPopup(): JBPopup = JBPopupFactory.getInstance()
Expand Down Expand Up @@ -484,6 +498,20 @@ class CodeWhispererPopupManager {
window?.addComponentListener(windowListener)
Disposer.register(sessionContext) { window?.removeComponentListener(windowListener) }
}

val suggestionHoverEnterListener: EditorMouseMotionListener = object : EditorMouseMotionListener {
override fun mouseMoved(e: EditorMouseEvent) {
if (e.inlay != null) {
showPopup(sessionContext, force = true)
} else {
sessionContext.project.messageBus.syncPublisher(
CodeWhispererService.CODEWHISPERER_INTELLISENSE_POPUP_ON_HOVER,
).onEnter()
}
super.mouseMoved(e)
}
}
editor.addEditorMouseMotionListener(suggestionHoverEnterListener, sessionContext)
}

private fun updateSelectedRecommendationLabelText(validSelectedIndex: Int, validCount: Int) {
Expand Down Expand Up @@ -560,10 +588,6 @@ class CodeWhispererPopupManager {
}
}

fun hasConflictingPopups(editor: Editor): Boolean =
ParameterInfoController.existsWithVisibleHintForEditor(editor, true) ||
LookupManager.getActiveLookup(editor) != null

fun findNewSelectedIndex(isReverse: Boolean, selectedIndex: Int): Int {
val start = if (selectedIndex == -1) 0 else selectedIndex
val previews = CodeWhispererService.getInstance().getAllSuggestionsPreviewInfo()
Expand Down
Loading

0 comments on commit cc2583d

Please sign in to comment.