Skip to content

Commit ff3ecc8

Browse files
CopilotbedaHovorka
andauthored
Remove incorrect Doubleton deprecation - no Kotlin stdlib equivalent (#19)
* Remove incorrect Doubleton deprecation - no Kotlin stdlib equivalent exists --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
1 parent ac41705 commit ff3ecc8

2 files changed

Lines changed: 52 additions & 30 deletions

File tree

CLAUDE.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -959,18 +959,16 @@ None. All critical bugs identified by SonarQube have been fixed.
959959

960960
**Recommendation:** Review with domain expert if high-precision rendering is required.
961961

962-
#### DEFERRED-003: Doubleton Missing equals() Override
962+
#### RESOLVED: Doubleton equals() Override
963963

964-
**Severity:** Minor (SonarQube rule java:S1206)
965-
**File:** `src/main/java/cz/vutbr/fit/interlockSim/util/Doubleton.java` (line 85)
964+
**Status:** RESOLVED (equals() override added during Kotlin migration)
965+
**File:** `src/main/kotlin/cz/vutbr/fit/interlockSim/util/Doubleton.kt` (line 110)
966966

967-
**Description:** Class overrides `hashCode()` but not `equals()`, violating the hashCode/equals contract.
967+
**Description:** Class now properly overrides both `hashCode()` and `equals()`, satisfying the contract.
968968

969-
**Impact:** Potential incorrect behavior when Doubleton objects are used in hash-based collections.
969+
**Resolution:** The equals() method was added during Kotlin migration. Additionally, the incorrect `@Deprecated` annotation was removed after analysis showed that Doubleton has no equivalent in Kotlin's standard library. Kotlin's `Pair` is ordered (A,B ≠ B,A), while Doubleton is unordered (A,B = B,A) and supports associated values, making it essential for representing bidirectional graph edges.
970970

971-
**Workaround:** Doubleton class is marked `@Deprecated`. Avoid using in new code.
972-
973-
**Recommendation:** Replace Doubleton with modern alternatives (e.g., `Map.Entry`, records) in future modernization.
971+
**Documentation:** Updated KDoc explains why Doubleton cannot be replaced with Kotlin's Pair.
974972

975973
### Design Limitations
976974

@@ -1048,8 +1046,9 @@ The codebase has been analyzed for deprecated Java standard library APIs. This i
10481046
- Easy fix: Use `Integer.valueOf()` or autoboxing
10491047

10501048
**MEDIUM Priority:**
1051-
- Internal project classes marked deprecated (`Doubleton`, `TreeMultiMap`) - 55 occurrences
1049+
- Internal project classes marked deprecated (`TreeMultiMap`) - ~27 occurrences
10521050
- These are project-specific deprecations, not Java SE
1051+
- Note: `Doubleton` deprecation was removed after analysis showed no Kotlin stdlib equivalent
10531052
- Require design review to determine replacement strategy
10541053

10551054
### Monitoring

src/main/kotlin/cz/vutbr/fit/interlockSim/util/Doubleton.kt

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,31 @@ import java.util.AbstractSet
1313
import java.util.NoSuchElementException
1414

1515
/**
16-
* Pair of nodes for implementation ADT ExtendedUnorientedGraph
17-
* Represents combination of two elements
18-
* @param <T> type of elements
19-
* @param <V> type of additional information
16+
* Unordered pair of nodes for implementation ADT ExtendedUnorientedGraph.
2017
*
21-
* @deprecated should be replaced in kotlin with library thing like Pair
18+
* Represents an unordered combination of two distinct elements with associated values.
19+
* Unlike Kotlin's [Pair], this class provides **order-independent equality**:
20+
* `Doubleton(A, B) == Doubleton(B, A)`.
21+
*
22+
* **Key Features:**
23+
* - Extends [AbstractSet] providing set semantics
24+
* - Enforces element distinctness (first != second)
25+
* - Order-independent equality and commutative hashCode
26+
* - Associated values for each element accessible via [getValue]
27+
* - Mutable values via [setValues]
28+
* - Suitable as HashMap key with proper hash-based collection behavior
29+
*
30+
* **Why not use Kotlin's Pair?**
31+
* - [Pair] is ordered: `Pair(A, B) != Pair(B, A)`
32+
* - [Pair] has no associated values mechanism
33+
* - [Pair] is not a Set and doesn't enforce distinctness
34+
*
35+
* This class is essential for representing unordered edges in graph structures where
36+
* the relationship between nodes is bidirectional and order-independent.
37+
*
38+
* @param T type of elements (the two nodes)
39+
* @param V type of additional information associated with each element
2240
*/
23-
@Deprecated(
24-
message = "Should be replaced in kotlin with library thing like Pair",
25-
replaceWith = ReplaceWith("Pair<T, V>")
26-
)
2741
class Doubleton<T, V> : AbstractSet<T> {
2842
enum class IteratorState {
2943
INIT,
@@ -63,21 +77,25 @@ class Doubleton<T, V> : AbstractSet<T> {
6377
private var secondValue: V? = null
6478

6579
/**
66-
* Create with additional information
67-
* @param first
68-
* @param second
69-
* @param firstValue
70-
* @param secondValue
80+
* Creates a Doubleton with associated values for each element.
81+
*
82+
* @param first the first element
83+
* @param second the second element (must be distinct from first)
84+
* @param firstValue the value associated with the first element
85+
* @param secondValue the value associated with the second element
86+
* @throws IllegalArgumentException if first equals second
7187
*/
7288
constructor(first: T, second: T, firstValue: V, secondValue: V) : this(first, second) {
7389
this.firstValue = firstValue
7490
this.secondValue = secondValue
7591
}
7692

7793
/**
78-
* Create without additional information
79-
* @param first
80-
* @param second
94+
* Creates a Doubleton without initial associated values.
95+
*
96+
* @param first the first element
97+
* @param second the second element (must be distinct from first)
98+
* @throws IllegalArgumentException if first equals second
8199
*/
82100
constructor(first: T, second: T) {
83101
if (first == second) throw IllegalArgumentException("arguments is equal")
@@ -120,8 +138,11 @@ class Doubleton<T, V> : AbstractSet<T> {
120138
override fun isEmpty(): Boolean = false
121139

122140
/**
123-
* @param key
124-
* @return value assigned to key
141+
* Retrieves the value associated with the specified element.
142+
*
143+
* @param key the element whose associated value is to be returned
144+
* @return the value associated with the key, or null if no value has been set
145+
* @throws IllegalArgumentException if the key is not contained in this Doubleton
125146
*/
126147
fun getValue(key: T): V? {
127148
val secondEq = nullEq(key, second)
@@ -142,8 +163,10 @@ class Doubleton<T, V> : AbstractSet<T> {
142163
}
143164

144165
/**
145-
* @param first
146-
* @param second
166+
* Sets the associated values for both elements.
167+
*
168+
* @param first the value to associate with the first element
169+
* @param second the value to associate with the second element
147170
*/
148171
fun setValues(
149172
first: V,

0 commit comments

Comments
 (0)