From 9c83e5bcd266e14665b45c78fd0c093a8b9ba2b2 Mon Sep 17 00:00:00 2001 From: Vest Date: Thu, 25 Jun 2026 22:15:39 +0200 Subject: [PATCH] spotbugs: suppress 6 design-intentional cast/CT findings Add method/constructor-level @SuppressFBWarnings with one-line justifications for casts and constructor-throws that are intentional by design. - BC_UNCONFIRMED_CAST @ ConcretePersistentTransitionChoice.setChoiceActor: API contract documents @throws ClassCastException for non-PersistentChoiceActor; the cast is the contract. - BC_UNCONFIRMED_CAST @ FactGrouping.process: Only CDOMObject can have facts (per in-code comment); type system can't express this constraint as PCGenScoped is the wider interface. - BC_UNCONFIRMED_CAST_OF_RETURN_VALUE @ LevelInfoFacet.get: Facet's own cache; getComponentSet() always returns ArrayList. - BC_UNCONFIRMED_CAST_OF_RETURN_VALUE @ UnencumberedArmorFacet.getBestLoad: Facet's own cache; getComponentMap() always returns TreeMap>. - BC_UNCONFIRMED_CAST_OF_RETURN_VALUE @ UnencumberedLoadFacet.getBestLoad: Facet's own cache; getComponentMap() always returns TreeMap>. - CT_CONSTRUCTOR_THROW @ AbstractReferenceManufacturer: Abstract class; ManufacturableFactory is required and Objects.requireNonNull is the lightest defense against an unusable instance. --- .../pcgen/cdom/base/ConcretePersistentTransitionChoice.java | 2 ++ code/src/java/pcgen/cdom/content/fact/FactGrouping.java | 4 ++++ code/src/java/pcgen/cdom/facet/LevelInfoFacet.java | 4 ++++ .../pcgen/cdom/facet/analysis/UnencumberedArmorFacet.java | 4 ++++ .../java/pcgen/cdom/facet/analysis/UnencumberedLoadFacet.java | 4 ++++ .../pcgen/cdom/reference/AbstractReferenceManufacturer.java | 4 +++- 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/code/src/java/pcgen/cdom/base/ConcretePersistentTransitionChoice.java b/code/src/java/pcgen/cdom/base/ConcretePersistentTransitionChoice.java index 155fc65631c..e3be4b7e214 100644 --- a/code/src/java/pcgen/cdom/base/ConcretePersistentTransitionChoice.java +++ b/code/src/java/pcgen/cdom/base/ConcretePersistentTransitionChoice.java @@ -79,6 +79,8 @@ public ConcretePersistentTransitionChoice(SelectableSet set, Formul * if the given ChoiceActor is not a PersistentChoiceActor */ @Override + @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", + justification = "API contract documents @throws ClassCastException for non-PersistentChoiceActor; the cast is the contract") public void setChoiceActor(ChoiceActor actor) { choiceActor = (PersistentChoiceActor) actor; diff --git a/code/src/java/pcgen/cdom/content/fact/FactGrouping.java b/code/src/java/pcgen/cdom/content/fact/FactGrouping.java index 0658d33892f..4002b4674e0 100644 --- a/code/src/java/pcgen/cdom/content/fact/FactGrouping.java +++ b/code/src/java/pcgen/cdom/content/fact/FactGrouping.java @@ -24,6 +24,8 @@ import pcgen.cdom.grouping.GroupingCollection; import pcgen.cdom.grouping.GroupingInfo; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * A FactGrouping is a GroupingCollection that contains objects of a specific type (e.g. * Skill) that contain a specific value in a given FACT @@ -116,6 +118,8 @@ public String getInstructions() } @Override + @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", + justification = "Only CDOMObject can have facts (per in-code comment); type system can't express this constraint as PCGenScoped is the wider interface") public void process(PCGenScoped o, Consumer consumer) { //Cast can not fail (as only CDOMObject can have facts) diff --git a/code/src/java/pcgen/cdom/facet/LevelInfoFacet.java b/code/src/java/pcgen/cdom/facet/LevelInfoFacet.java index fbca31f0b87..6185df1f85f 100644 --- a/code/src/java/pcgen/cdom/facet/LevelInfoFacet.java +++ b/code/src/java/pcgen/cdom/facet/LevelInfoFacet.java @@ -25,6 +25,8 @@ import pcgen.cdom.facet.base.AbstractListFacet; import pcgen.core.pclevelinfo.PCLevelInfo; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * LevelInfoFacet stores the PCLevelInfo objects contained in a Player * Character. These store information about a specific Level (such as stat @@ -58,6 +60,8 @@ protected Collection getComponentSet() * @return The object in this LevelInfoFacet for the Player Character * represented by the given CharID and location. */ + @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", + justification = "Facet's own cache; getComponentSet() always returns ArrayList") public PCLevelInfo get(CharID id, int location) { List componentSet = (List) getCachedSet(id); diff --git a/code/src/java/pcgen/cdom/facet/analysis/UnencumberedArmorFacet.java b/code/src/java/pcgen/cdom/facet/analysis/UnencumberedArmorFacet.java index 6f63edd826e..8d3cde304dd 100644 --- a/code/src/java/pcgen/cdom/facet/analysis/UnencumberedArmorFacet.java +++ b/code/src/java/pcgen/cdom/facet/analysis/UnencumberedArmorFacet.java @@ -30,6 +30,8 @@ import pcgen.cdom.facet.event.DataFacetChangeListener; import pcgen.util.enumeration.Load; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * UnencumberedArmorFacet is a Facet that tracks the Load objects for * Unencumbered Armor that have been locked on a Player Character. @@ -111,6 +113,8 @@ protected Map> getComponentMap() * @return The best Load value to avoid encumberance from Armor for the * Player Character identified by the given CharID. */ + @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", + justification = "Facet's own cache; getComponentMap() always returns TreeMap>") public Load getBestLoad(CharID id) { TreeMap> map = (TreeMap>) getCachedMap(id); diff --git a/code/src/java/pcgen/cdom/facet/analysis/UnencumberedLoadFacet.java b/code/src/java/pcgen/cdom/facet/analysis/UnencumberedLoadFacet.java index 190a4584087..07d4ba2447c 100644 --- a/code/src/java/pcgen/cdom/facet/analysis/UnencumberedLoadFacet.java +++ b/code/src/java/pcgen/cdom/facet/analysis/UnencumberedLoadFacet.java @@ -30,6 +30,8 @@ import pcgen.cdom.facet.event.DataFacetChangeListener; import pcgen.util.enumeration.Load; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * UnencumberedLoadFacet is a Facet that tracks the Load objects for * Unencumbered movement that have been locked on a Player Character. @@ -111,6 +113,8 @@ protected Map> getComponentMap() * @return The best Load value to avoid encumberance from Load for the * Player Character identified by the given CharID. */ + @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", + justification = "Facet's own cache; getComponentMap() always returns TreeMap>") public Load getBestLoad(CharID id) { TreeMap> map = (TreeMap>) getCachedMap(id); diff --git a/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java b/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java index e34d0c30c79..cd40e258494 100644 --- a/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java +++ b/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java @@ -171,8 +171,10 @@ public abstract class AbstractReferenceManufacturer implemen * @throws IllegalArgumentException * if the given Class is null or the given Class does not have a * public, zero argument constructor - * + * */ + @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", + justification = "Abstract class; ManufacturableFactory is required and Objects.requireNonNull is the lightest defense against an unusable instance") public AbstractReferenceManufacturer(ManufacturableFactory fac) { if (fac == null)