|
33 | 33 | traces a record's synthesized accessor and canonical constructor), so this pair of exclusions is |
34 | 34 | specific to the record form. |
35 | 35 |
|
36 | | - 4. EI_EXPOSE_REP on the specific getters listed below, each returning a field whose type was just |
37 | | - changed (this PR) to extend the shared {@code ApifyResource} forward-compatibility base (an |
38 | | - {@code extra} catch-all map + package-private {@code @JsonAnySetter}), so unmodelled API fields |
39 | | - on nested value DTOs are preserved instead of silently dropped. That base class is not {@code |
40 | | - final} and holds a mutable {@code LinkedHashMap} field, which flips SpotBugs' mutability |
41 | | - heuristic for every subtype from "no public mutator -> immutable-enough, don't flag" to |
42 | | - "mutable -> flag every getter that returns one as a field of another class" - even though |
43 | | - nothing about this actually changed: {@code putExtra} stays package-private, {@code |
44 | | - getExtra()} still returns an unmodifiable view, and there is still no public way to mutate a |
45 | | - returned instance. Defensively copying on every getter call would require deep-cloning the |
46 | | - {@code extra} map each time, which is wasted work for a map that is (by construction) never |
47 | | - mutated after deserialization, so copying is not the fix here - the false positive is. Listed |
48 | | - per getter (not per class) to keep the exclusion exactly as narrow as the finding it suppresses. |
| 36 | + 4. EI_EXPOSE_REP on the specific getters listed below, each returning a field whose type extends |
| 37 | + the shared {@code ApifyResource} forward-compatibility base (an {@code extra} catch-all map + |
| 38 | + package-private {@code @JsonAnySetter}), so unmodelled API fields on nested value DTOs are |
| 39 | + preserved instead of silently dropped. That base class is not {@code final} and holds a mutable |
| 40 | + {@code LinkedHashMap} field, which flips SpotBugs' mutability heuristic for every subtype from |
| 41 | + "no public mutator -> immutable-enough, don't flag" to "mutable -> flag every getter that |
| 42 | + returns one as a field of another class" - a false positive: {@code putExtra} stays |
| 43 | + package-private, {@code getExtra()} still returns an unmodifiable view, and there is still no |
| 44 | + public way to mutate a returned instance. Defensively copying on every getter call would require |
| 45 | + deep-cloning the {@code extra} map each time, which is wasted work for a map that is (by |
| 46 | + construction) never mutated after deserialization, so copying is not the fix here - the false |
| 47 | + positive is. Listed per getter (not per class) to keep the exclusion exactly as narrow as the |
| 48 | + finding it suppresses. |
49 | 49 |
|
50 | 50 | 5. EI_EXPOSE_REP2 on {@code ListPublisher}'s constructor, which stores the caller-supplied {@code |
51 | 51 | CompletableFuture<List<T>>} straight into a field. A {@code CompletableFuture} is a handle to an |
|
0 commit comments