Skip to content

refactor(kits): inline user attribute removal in onRemoveUserAttribute#686

Closed
denischilik wants to merge 7 commits into
workstation/6.0-Releasefrom
feature/user-attribute-listener-on-remove-user-attribute
Closed

refactor(kits): inline user attribute removal in onRemoveUserAttribute#686
denischilik wants to merge 7 commits into
workstation/6.0-Releasefrom
feature/user-attribute-listener-on-remove-user-attribute

Conversation

@denischilik

@denischilik denischilik commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Background

Attribute removal for kits is consolidated on BaseAttributeListener.onRemoveUserAttribute so the SDK does not rely on a separate AttributeListener.removeUserAttribute contract. Kits now implement removal in one place, which aligns with the broader move toward UserAttributeListener-style APIs.

What Has Changed

  • Removed removeUserAttribute from AttributeListener; kits keep removal logic only in onRemoveUserAttribute.
  • Updated Adobe, Adobe Media, Apptimize, Branch, Braze (38–41), Comscore, Kochava, Localytics, Singular, AppsFlyer, and Urban Airship kits accordingly.
  • Renamed the AttributeListenerTestKit test hook to removeUserAttributeListener and adjusted dataplan blocking tests.

Screenshots/Video

N/A (SDK behavior change, no UI).

Checklist

  • I have performed a self-review of my own code.
  • I have made corresponding changes to the documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have tested this locally.

Additional Notes

Target branch: workstation/6.0-Release. Kits were validated with publishMavenPublicationToMavenLocal and testRelease using -Pmparticle.kit.mparticleFromMavenLocalOnly=true.

Introduce KitIntegration.BaseAttributeListener as the common superinterface
for AttributeListener and UserAttributeListener. Document it as a temporary
contract to enable incremental migration and smaller PRs.

Made-with: Cursor
Resolve via BaseAttributeListener before AttributeListener/UserAttributeListener
branches in onUserAttributesReceived and setUserAttribute(list).

Made-with: Cursor
UserAttributeListener.onRemoveUserAttribute now forwards to the existing
AttributeListener.removeUserAttribute implementation for braze-38 through braze-41.

Made-with: Cursor
Declare onRemoveUserAttribute on KitIntegration.BaseAttributeListener so
AttributeListener and UserAttributeListener implementors must implement it.
KitManagerImpl now dispatches removal once via BaseAttributeListener.

AttributeListener-only kits delegate onRemoveUserAttribute to removeUserAttribute;
AttributeListenerTestKit updated accordingly.

Made-with: Cursor
Drop void removeUserAttribute(String) from KitIntegration.AttributeListener.
Kits keep the same logic as private-style helpers (fun removeUserAttribute
without override) and still satisfy BaseAttributeListener via
onRemoveUserAttribute. AdobeKitBase implements onRemoveUserAttribute by
delegating to removeUserAttribute.

Made-with: Cursor
Move kit-specific handling from removed helper methods into
BaseAttributeListener.onRemoveUserAttribute implementations.
Rename AttributeListenerTestKit callback to removeUserAttributeListener.
Fix Braze custom-key branch for Kotlin smart-cast in Braze callback.

Made-with: Cursor
@denischilik denischilik requested a review from a team as a code owner March 30, 2026 20:16
@cursor

cursor Bot commented Mar 30, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches core kit forwarding and public kit interfaces for user-attribute removal; any kit not updated to the new callback signature could stop receiving removals or fail to compile.

Overview
Unifies user-attribute removal across kits by removing AttributeListener.removeUserAttribute and routing removals through a shared BaseAttributeListener.onRemoveUserAttribute(key, FilteredMParticleUser) contract.

KitManagerImpl now checks supportsAttributeLists() via the shared base listener and calls a single removal callback for both AttributeListener and UserAttributeListener. Multiple bundled kits are updated to implement removal in onRemoveUserAttribute (or explicitly no-op), and the attribute-listener test kit + dataplan blocking tests are adjusted for the renamed removal hook.

Written by Cursor Bugbot for commit 8b60dc3. This will update automatically on new commits. Configure here.

@denischilik denischilik changed the base branch from main to workstation/6.0-Release March 30, 2026 20:17
Document intentional empty overrides in Adobe, AppsFlyer, Branch, Braze,
and Kochava kits to satisfy SonarQube analysis.

Made-with: Cursor
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
69.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@denischilik denischilik deleted the feature/user-attribute-listener-on-remove-user-attribute branch March 31, 2026 13:22

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

if (key == null) {
return
}
var keyMut = key

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unnecessary mutable variable keyMut is never reassigned

Low Severity

var keyMut = key is declared as mutable but never reassigned — the $-prefix stripping now uses a separate var customKey local. In the old removeUserAttribute, the equivalent variable was mutated in-place, but that mutation was moved to customKey, making keyMut effectively a val. Using var here is misleading and suggests future mutation that never happens. Same issue in braze-39, braze-40, and braze-41.

Additional Locations (2)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant