Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -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.30-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
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
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 @@ -134,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 @@ -142,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 @@ -6,11 +6,16 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup
import com.intellij.icons.AllIcons
import com.intellij.ide.BrowserUtil
import com.intellij.idea.AppMode
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.ActionToolbar
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.KeyboardShortcut
import com.intellij.openapi.actionSystem.Presentation
import com.intellij.openapi.actionSystem.impl.ActionButton
import com.intellij.openapi.keymap.KeymapUtil
import com.intellij.openapi.keymap.MacKeymapUtil
import com.intellij.openapi.util.SystemInfo
import com.intellij.ui.IdeBorderFactory
import com.intellij.ui.components.ActionLink
import com.intellij.util.ui.UIUtil
Expand Down Expand Up @@ -43,10 +48,38 @@ import javax.swing.JPanel

class CodeWhispererPopupComponents {
val prevButton = createNavigationButton(
message("codewhisperer.popup.button.prev", POPUP_DIM_HEX)
message(
"codewhisperer.popup.button.prev",
POPUP_DIM_HEX,
run {
// TODO: Doesn't reflect dynamically if users change but didn't restart IDE
val shortcut = ActionManager.getInstance().getAction("codewhisperer.inline.navigate.previous")
.shortcutSet.shortcuts.first()
val keyStroke = (shortcut as KeyboardShortcut).firstKeyStroke
if (SystemInfo.isMac) {
MacKeymapUtil.getKeyStrokeText(keyStroke, " ", true)
} else {
KeymapUtil.getKeystrokeText(keyStroke)
}
}
)
)
val nextButton = createNavigationButton(
message("codewhisperer.popup.button.next", POPUP_DIM_HEX)
message(
"codewhisperer.popup.button.next",
POPUP_DIM_HEX,
run {
// TODO: Doesn't reflect dynamically if users change but didn't restart IDE
val shortcut = ActionManager.getInstance().getAction("codewhisperer.inline.navigate.next")
.shortcutSet.shortcuts.first()
val keyStroke = (shortcut as KeyboardShortcut).firstKeyStroke
if (SystemInfo.isMac) {
MacKeymapUtil.getKeyStrokeText(keyStroke, " ", true)
} else {
KeymapUtil.getKeystrokeText(keyStroke)
}
}
)
).apply {
preferredSize = prevButton.preferredSize
}
Expand Down
Loading