Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
754a269
initial commit
samgst-amazon Nov 19, 2024
bca91eb
run on startup
samgst-amazon Nov 20, 2024
d894d86
detekt
samgst-amazon Nov 20, 2024
6beeadc
move vals
samgst-amazon Nov 20, 2024
c233764
remote resource implementation
samgst-amazon Nov 20, 2024
6f6dd6d
comments
samgst-amazon Nov 20, 2024
6bf7007
detekt
samgst-amazon Nov 20, 2024
9d32c86
Validate file before saving
samgst-amazon Nov 21, 2024
7952d9b
cache path
samgst-amazon Nov 21, 2024
fd2d1fb
observer implementation
samgst-amazon Nov 21, 2024
cff580f
deserialize notifs from file
samgst-amazon Nov 21, 2024
2d2ffaf
detekt
samgst-amazon Nov 21, 2024
a08194c
remove unused interface
samgst-amazon Nov 22, 2024
17b49fc
internal class
samgst-amazon Nov 22, 2024
c5718f7
Fix observer
samgst-amazon Nov 22, 2024
691d131
etag singleton state component
samgst-amazon Nov 22, 2024
4e588bf
add telemetry
samgst-amazon Nov 22, 2024
a4427ab
atomicBoolean
samgst-amazon Nov 22, 2024
2ce16c3
initialize once per IDE startup
samgst-amazon Nov 22, 2024
c54884d
code scan
samgst-amazon Nov 22, 2024
5f140d4
Omit (Unit)
samgst-amazon Nov 22, 2024
b8b6950
specify etag storage location
samgst-amazon Nov 22, 2024
098bb78
detekt
samgst-amazon Nov 22, 2024
ce834c8
fix detekt issues
samgst-amazon Nov 22, 2024
50ef8fd
basic tests
samgst-amazon Nov 23, 2024
6c76ec4
no star imports
samgst-amazon Nov 23, 2024
cc02c33
coroutine scope delay instead of thread.sleep
samgst-amazon Nov 25, 2024
f04da83
feedback fixes
samgst-amazon Nov 25, 2024
f81d96f
test fix
samgst-amazon Nov 25, 2024
9375226
Application Exists for tests
samgst-amazon Nov 25, 2024
7add727
endpoint object
samgst-amazon Nov 25, 2024
35a2b69
merge conflict
samgst-amazon Nov 25, 2024
aacc8e8
detekt
samgst-amazon Nov 25, 2024
d75d8e9
detekt fixes
samgst-amazon Nov 25, 2024
a14e6c1
boolean flag
samgst-amazon Nov 25, 2024
cbc2f4d
boolean flag
samgst-amazon Nov 25, 2024
580674e
update tests
samgst-amazon Nov 25, 2024
fcd46a6
move startup flag handling to processBase
samgst-amazon Nov 26, 2024
8fba3a3
fix delay
samgst-amazon Nov 26, 2024
84ed1ef
fix delay
samgst-amazon Nov 26, 2024
26caf31
Notification dismissal state tracking (#5129)
samgst-amazon Nov 27, 2024
8546d4a
endpoint as registryKey
samgst-amazon Nov 27, 2024
22420b1
detekt
samgst-amazon Nov 27, 2024
01bb9ef
Merge branch 'feature/ideNotifs' into samgst/notificationPolling
samgst-amazon Nov 27, 2024
7097fd9
fix startup issues
samgst-amazon Nov 27, 2024
49924d5
Expiry issues
samgst-amazon Nov 27, 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 @@ -32,9 +32,11 @@ class DefaultRemoteResourceResolver(
private fun internalResolve(resource: RemoteResource): Path {
val expectedLocation = cacheBasePath.resolve(resource.name)
val current = expectedLocation.existsOrNull()
if (current != null && !isExpired(current, resource)) {
LOG.debug { "Existing file ($current) for ${resource.name} is present and not expired - using it." }
return current
if (resource.name != "notifications.json") {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rli This feels hacky, but its one way to get around this issue, the other way I think we could maybe do this is to just set the expiry time to a very short window so that the file is always seen as expired by the time polling makes this call to the endpoint

if ((current != null && !isExpired(current, resource))) {
LOG.debug { "Existing file ($current) for ${resource.name} is present and not expired - using it." }
return current
}
}

LOG.debug { "Current file for ${resource.name} does not exist or is expired. Attempting to fetch from ${resource.urls}" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

<postStartupActivity implementation="software.aws.toolkits.jetbrains.core.plugin.PluginAutoUpdater"/>
<postStartupActivity implementation="software.aws.toolkits.jetbrains.core.AwsTelemetryPrompter"/>
<postStartupActivity implementation="software.aws.toolkits.jetbrains.services.telemetry.AwsToolkitStartupMetrics"/>

<registryKey key="aws.dev.useDAG" description="True if DAG should be used instead of authorization_grant with PKCE"
defaultValue="false" restartRequired="false"/>
Expand All @@ -77,6 +78,9 @@
restartRequired="true"/>
<registryKey key="aws.toolkit.developerMode" description="Enables features to facilitate development of the toolkit" restartRequired="false"
defaultValue="false"/>
<registryKey key="aws.toolkit.notification.endpoint" description="Endpoint for AWS Toolkit notifications"
defaultValue="https://idetoolkits-hostedfiles.amazonaws.com/Notifications/Jetbrains/emergency/1.x.json" restartRequired="true"/>


<notificationGroup id="aws.plugin.version.mismatch" displayType="STICKY_BALLOON" key="aws.settings.title"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ class NotConditionDeserializer : JsonDeserializer<NotificationExpression.NotCond
}
}

// Create a custom deserializer if needed
class NotificationTypeDeserializer : JsonDeserializer<NotificationScheduleType>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): NotificationScheduleType =
NotificationScheduleType.fromString(p.valueAsString)
}

private fun JsonNode.toNotificationExpressions(p: JsonParser): List<NotificationExpression> = this.map { element ->
val parser = element.traverse(p.codec)
parser.nextToken()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,32 @@
)

data class NotificationSchedule(
val type: String,
)
@JsonDeserialize(using = NotificationTypeDeserializer::class)
val type: NotificationScheduleType,
) {
constructor(type: String) : this(NotificationScheduleType.fromString(type))
}

enum class NotificationSeverity {
INFO,
WARNING,
CRITICAL,
}

enum class NotificationScheduleType {
STARTUP,
EMERGENCY,
;

companion object {
fun fromString(value: String): NotificationScheduleType =
when (value.lowercase()) {
"startup" -> STARTUP
else -> EMERGENCY

Check warning on line 51 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationFormatUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationFormatUtils.kt#L51

Added line #L51 was not covered by tests
}
}
}

Check warning on line 54 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationFormatUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationFormatUtils.kt#L54

Added line #L54 was not covered by tests

data class NotificationContentDescriptionLocale(
@JsonProperty("en-US")
val locale: NotificationContentDescription,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
init {
isOpaque = false
addToCenter(wrapper)
ProcessNotificationsBase.showBannerNotification.forEach {
updateNotificationPanel(it.value)
BannerNotificationService.getInstance().getNotifications().forEach { (_, content) ->
updateNotificationPanel(content)

Check warning on line 19 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPanel.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPanel.kt#L18-L19

Added lines #L18 - L19 were not covered by tests
}
}

private fun removeNotificationPanel(notificationId: String) = runInEdt {
ProcessNotificationsBase.showBannerNotification.remove(notificationId) // TODO: add id to dismissed notification list
BannerNotificationService.getInstance().removeNotification(notificationId)
NotificationDismissalState.getInstance().dismissNotification(notificationId)

Check warning on line 25 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPanel.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPanel.kt#L24-L25

Added lines #L24 - L25 were not covered by tests
wrapper.removeAll()
}

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

package software.aws.toolkits.jetbrains.core.notifications

import com.fasterxml.jackson.module.kotlin.readValue
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.util.registry.Registry
import com.intellij.util.Alarm
import com.intellij.util.AlarmFactory
import com.intellij.util.io.HttpRequests
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import software.aws.toolkits.core.utils.RemoteResolveParser
import software.aws.toolkits.core.utils.RemoteResource
import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.warn
import software.aws.toolkits.jetbrains.core.DefaultRemoteResourceResolverProvider
import software.aws.toolkits.jetbrains.core.RemoteResourceResolverProvider
import software.aws.toolkits.telemetry.Component
import software.aws.toolkits.telemetry.ToolkitTelemetry

Check warning on line 24 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Usage of redundant or deprecated syntax or deprecated symbols

Remove deprecated symbol import

Check warning on line 24 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Usage of redundant or deprecated syntax or deprecated symbols

'ToolkitTelemetry' is deprecated. Use type-safe metric builders

Check warning

Code scanning / QDJVMC

Usage of redundant or deprecated syntax or deprecated symbols Warning

Remove deprecated symbol import

Check warning

Code scanning / QDJVMC

Usage of redundant or deprecated syntax or deprecated symbols Warning

'ToolkitTelemetry' is deprecated. Use type-safe metric builders
import java.io.InputStream
import java.time.Duration
import java.util.concurrent.atomic.AtomicBoolean

private const val MAX_RETRIES = 3
private const val RETRY_DELAY_MS = 1000L

object NotificationFileValidator : RemoteResolveParser {
override fun canBeParsed(data: InputStream): Boolean =
try {
NotificationMapperUtil.mapper.readValue<NotificationsList>(data)
true
} catch (e: Exception) {
false
}

Check warning on line 39 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L34-L39

Added lines #L34 - L39 were not covered by tests
}

object NotificationEndpoint {
fun getEndpoint(): String =
Registry.get("aws.toolkit.notification.endpoint").asString()
}

@Service(Service.Level.APP)
internal final class NotificationPollingService : Disposable {

Check warning on line 48 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Redundant modality modifier

Redundant modality modifier

Check warning

Code scanning / QDJVMC

Redundant modality modifier Warning

Redundant modality modifier
private val isFirstPoll = AtomicBoolean(true)
private val observers = mutableListOf<() -> Unit>()
private val alarm = AlarmFactory.getInstance().create(Alarm.ThreadToUse.POOLED_THREAD, this)
private val pollingIntervalMs = Duration.ofMinutes(10).toMillis()
private val resourceResolver: RemoteResourceResolverProvider = DefaultRemoteResourceResolverProvider()
private val notificationsResource = object : RemoteResource {
override val name: String = "notifications.json"
override val urls: List<String> = listOf(NotificationEndpoint.getEndpoint())
override val remoteResolveParser: RemoteResolveParser = NotificationFileValidator
}

fun startPolling() {
val newNotifications = runBlocking { pollForNotifications() }
if (newNotifications) {
notifyObservers()
}
alarm.addRequest(
{ startPolling() },

Check warning on line 66 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L66

Added line #L66 was not covered by tests
pollingIntervalMs
)
}

/**
* Main polling function that checks for updates and downloads if necessary
* Returns the parsed notifications if successful, null otherwise
*/
private suspend fun pollForNotifications(): Boolean {
var retryCount = 0
var lastException: Exception? = null

while (retryCount < MAX_RETRIES) {
try {
val newETag = getNotificationETag()
if (newETag == NotificationEtagState.getInstance().etag) {
// for when we need to notify on first poll even when there's no new ETag
if (isFirstPoll.compareAndSet(true, false)) {
notifyObservers()
}
return false
}
resourceResolver.get()
.resolve(notificationsResource)
.toCompletableFuture()
.get()

Check warning on line 92 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Possibly blocking call in non-blocking context

Possibly blocking call in non-blocking context could lead to thread starvation

Check warning

Code scanning / QDJVMC

Possibly blocking call in non-blocking context Warning

Possibly blocking call in non-blocking context could lead to thread starvation
NotificationEtagState.getInstance().etag = newETag
return true
} catch (e: Exception) {
lastException = e
LOG.error(e) { "Failed to poll for notifications (attempt ${retryCount + 1}/$MAX_RETRIES)" }
retryCount++

Check warning on line 98 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L95-L98

Added lines #L95 - L98 were not covered by tests
if (retryCount < MAX_RETRIES) {
val backoffDelay = RETRY_DELAY_MS * (1L shl (retryCount - 1))
delay(backoffDelay)

Check warning on line 101 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L100-L101

Added lines #L100 - L101 were not covered by tests
}
}
}
emitFailureMetric(lastException)
return false

Check warning on line 106 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L105-L106

Added lines #L105 - L106 were not covered by tests
}

private fun getNotificationETag(): String =
try {
HttpRequests.request(NotificationEndpoint.getEndpoint())
.userAgent("AWS Toolkit for JetBrains")
.connect { request ->
request.connection.headerFields["ETag"]?.firstOrNull().orEmpty()
}
} catch (e: Exception) {
LOG.warn { "Failed to fetch notification ETag: $e.message" }

Check warning on line 117 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L116-L117

Added lines #L116 - L117 were not covered by tests
throw e
}

private fun emitFailureMetric(e: Exception?) {
ToolkitTelemetry.showNotification(

Check warning on line 122 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Usage of redundant or deprecated syntax or deprecated symbols

'ToolkitTelemetry' is deprecated. Use type-safe metric builders

Check warning

Code scanning / QDJVMC

Usage of redundant or deprecated syntax or deprecated symbols Warning

'ToolkitTelemetry' is deprecated. Use type-safe metric builders
project = null,
component = Component.Filesystem,
id = "",
reason = "Failed to poll for notifications",
success = false,

Check warning on line 127 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L122-L127

Added lines #L122 - L127 were not covered by tests
reasonDesc = "${e?.javaClass?.simpleName ?: "Unknown"}: ${e?.message ?: "No message"}",
)
}

Check warning on line 130 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationPollingService.kt#L130

Added line #L130 was not covered by tests

fun addObserver(observer: () -> Unit) = observers.add(observer)

private fun notifyObservers() {
observers.forEach { observer ->
observer()
}
}

override fun dispose() {
alarm.dispose()
}

companion object {
private val LOG = getLogger<NotificationPollingService>()
fun getInstance(): NotificationPollingService =
ApplicationManager.getApplication().getService(NotificationPollingService::class.java)
}
}
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.core.notifications

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.ProjectActivity
import java.util.concurrent.atomic.AtomicBoolean

internal class NotificationServiceInitializer : ProjectActivity {

private val initialized = AtomicBoolean(false)

override suspend fun execute(project: Project) {
if (ApplicationManager.getApplication().isUnitTestMode) return
if (initialized.compareAndSet(false, true)) {
val service = NotificationPollingService.getInstance()
service.startPolling()

Check warning on line 19 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationServiceInitializer.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationServiceInitializer.kt#L18-L19

Added lines #L18 - L19 were not covered by tests
}
}

Check warning on line 21 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationServiceInitializer.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationServiceInitializer.kt#L21

Added line #L21 was not covered by tests
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service

@Service
@State(name = "notificationDismissals", storages = [Storage("aws.xml", roamingType = RoamingType.DISABLED)])
class NotificationDismissalState : PersistentStateComponent<NotificationDismissalConfiguration> {
private val state = NotificationDismissalConfiguration()

override fun getState(): NotificationDismissalConfiguration = state

Check warning on line 18 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L18

Added line #L18 was not covered by tests

override fun loadState(state: NotificationDismissalConfiguration) {
this.state.dismissedNotificationIds.clear()
this.state.dismissedNotificationIds.addAll(state.dismissedNotificationIds)
}

Check warning on line 23 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L21-L23

Added lines #L21 - L23 were not covered by tests

fun isDismissed(notificationId: String): Boolean =
state.dismissedNotificationIds.contains(notificationId)

fun dismissNotification(notificationId: String) {
state.dismissedNotificationIds.add(notificationId)
}

companion object {
fun getInstance(): NotificationDismissalState =
service()

Check warning on line 34 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L34

Added line #L34 was not covered by tests
}
}

data class NotificationDismissalConfiguration(
var dismissedNotificationIds: MutableSet<String> = mutableSetOf(),
)

@Service
@State(name = "notificationEtag", storages = [Storage("aws.xml", roamingType = RoamingType.DISABLED)])
class NotificationEtagState : PersistentStateComponent<NotificationEtagConfiguration> {
private val state = NotificationEtagConfiguration()

override fun getState(): NotificationEtagConfiguration = state

Check warning on line 47 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L47

Added line #L47 was not covered by tests

override fun loadState(state: NotificationEtagConfiguration) {
this.state.etag = state.etag
}

Check warning on line 51 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L50-L51

Added lines #L50 - L51 were not covered by tests

var etag: String?
get() = state.etag
set(value) {
state.etag = value
}

companion object {
fun getInstance(): NotificationEtagState =
service()
}
}

data class NotificationEtagConfiguration(
var etag: String? = null,
)

@Service
class BannerNotificationService {
private val notifications = mutableMapOf<String, BannerContent>()

Check warning on line 71 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L69-L71

Added lines #L69 - L71 were not covered by tests

fun addNotification(id: String, content: BannerContent) {
notifications[id] = content
}

Check warning on line 75 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L74-L75

Added lines #L74 - L75 were not covered by tests

fun getNotifications(): Map<String, BannerContent> = notifications

Check warning on line 77 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L77

Added line #L77 was not covered by tests

fun removeNotification(id: String) {
notifications.remove(id)
}

Check warning on line 81 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L80-L81

Added lines #L80 - L81 were not covered by tests

companion object {
fun getInstance(): BannerNotificationService =
service()

Check warning on line 85 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/NotificationStateUtils.kt#L85

Added line #L85 was not covered by tests
}
}
Loading
Loading