spotbugs cleanups: drop dead fields/locals + small fixes#7634
Open
Vest wants to merge 2 commits into
Open
Conversation
Six conservative cleanups across cdom; all of URF_UNREAD_FIELD, one RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE, and one DLS_DEAD_LOCAL_STORE in the cdom package go away. Fixes (real code removals): - CalcBonusFacet: drop unused templateFacet field, its setter, the associated import, and the matching <property> in applicationContext.xml. The commented-out templateFacet.addDataFacetChangeListener call in init() confirms it was already inactive; Spring only injected a wasted reference. - ClassSkillChoiceActor.applyChoice: drop dead levelIndex++ that ran immediately before the loop break; the increment was never read. - AddedTemplateFacet.dataRemoved: drop redundant null check on the return of getFromSource(); its Javadoc and code already guarantee a non-null collection (matches the dataAdded() sibling). Suppressions with rationale (field intentionally retained): - AbstractPCGenModifier.references: holds a strong reference to keep the underlying Indirects from being GC'd. The existing javadoc says "DO NOT DELETE THIS EVEN THOUGH IT APPEARS UNUSED"; add @SuppressFBWarnings(URF_UNREAD_FIELD) with the GC-anchor rationale. - CharID.myFacetCache / DataSetID.myFacetCache: debugger-visible views of the facet cache, documented as such; add @SuppressFBWarnings( URF_UNREAD_FIELD) so SpotBugs stops flagging them. Deferred (not in this PR): - AbilityFromClassChoiceSet.java:144 DLS_DEAD_LOCAL_STORE: paired with an explicit "TODO This is a bug -> it was not properly gathering before" comment; touching the dead store would mask the known bug. - FactSetParser.unparse PZLA_PREFER_ZERO_LENGTH_ARRAYS: returning null on the error path (after addWriteMessage) matches the project-wide token unparse convention; callers in TokenSupport explicitly null-check. Verified: compileJava clean, pcgen.cdom.* (2355) and plugin.lsttokens.* (9713) tests both pass with 0 failures. SpotBugs main report: URF and RCN bug-pattern categories now empty; DLS reduced from 2 to 1 in CDOM; no new findings introduced.
The 2013-12-01 commit d9a5fca ('Potential speedup for template based dragons') commented out the TemplateFacet listener registration but left the field, setter, and Spring wiring as undead code (cleaned up earlier in this PR). The 2012 design treated TemplateFacet events as the canonical recalc trigger; the 2013 change moved that responsibility to explicit callers like PlayerCharacter.addTemplate. Adding a class-Javadoc note so the convention isn't reverse-engineered from git history every time the file is touched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Conservative SpotBugs cleanup in cdom: removes the entire URF_UNREAD_FIELD and RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE bug-pattern categories from the report, plus one DLS_DEAD_LOCAL_STORE. No behavior changes other than dropping a Spring property that injected an unused reference.
Fixes
CalcBonusFacet.templateFacetTemplateFacetimport, and the<property name="templateFacet"/>inapplicationContext.xml. The matchingaddDataFacetChangeListenercall ininit()was already commented out, so behavior was effectively dead. (See deep dive below — researched the 2013 history to confirm this was a deliberate optimization, not a forgotten line.)AbstractPCGenModifier.references@SuppressFBWarnings(URF_UNREAD_FIELD)with the GC-anchor rationale.CharID.myFacetCache@SuppressFBWarnings(URF_UNREAD_FIELD).DataSetID.myFacetCacheCharID. Add@SuppressFBWarnings(URF_UNREAD_FIELD).AddedTemplateFacet.dataRemovedgetFromSource(...); its javadoc and code already guarantee a non-null collection (thedataAddedsibling already usesisEmpty()).ClassSkillChoiceActor.applyChoicelevelIndex++immediately before the loopbreak;— increment never read.Plus a follow-up commit adding a Javadoc note on
CalcBonusFacetitself (see deep dive).Why deleting
templateFacetwas the right call — historical deep diveThe agent's initial pass spotted
templateFacetas unread and removed it, but the surrounding context (a commented-out listener registration and a 2013 commit message about "template based dragons") warranted real investigation. Here's what the git history and code audit revealed:1. Original design (2012)
Commit
ab28c61112(thpr, 2012-02-05, "Move BonusCalculation Trigger out to facet for Race, Template, Deity") introducedCalcBonusFacetwith three listeners — race, deity, template — all firingaPC.calcActiveBonuses()on add/remove. Templates were treated as a canonical recalc trigger via the facet event chain.2. The 2013 deactivation
Commit
d9a5fcaed3(jdempsey, 2013-12-01, "Potential speedup for template based dragons") commented out the template listener:public void init() { raceFacet.addDataFacetChangeListener(5000, this); deityFacet.addDataFacetChangeListener(5000, this); - templateFacet.addDataFacetChangeListener(5000, this); + //templateFacet.addDataFacetChangeListener(5000, this); }The "dragons" reference is to D&D dragon NPCs being template-stacked: each template add or remove was firing a full
calcActiveBonuses()walk, and on dragons this could fire many times per user action.3. Why deactivation was safe
PlayerCharacter.addTemplatealready callscalcActiveBonuses()explicitly (line 4364, and has done so since well before 2013). TheTemplateFacetlistener was firing a second, redundant recalc on every template add — pure waste.For removal paths, all 7 callsites of
PlayerCharacter.removeTemplateeither recalc explicitly afterwards (e.g.CharacterFacadeImpl:3541theCharacter.calcActiveBonuses();) or are inside an outer event whose recalc is still wired through theraceFacetlistener (AddedTemplateFacet.dataRemovedcascades fromRaceFacet.dataRemoved).removeTemplatecallerPlayerCharacter:1567,1574(level adjust loop)PlayerCharacter:7778(subtemplate fromaddTemplate)addTemplaterecalcsCharacterFacadeImpl:3540calcActiveBonuses()on next lineTemplateInfoTabCharacterFacadeImpl— coveredAddedTemplateFacet.dataRemoved(3 sites)raceFacetlistenerTemplateLst.removeChoice/add.TemplateToken.removeChoicePCGVer2Parser(load path)calcActiveBonuses()4. Why the cleanup is safe
The 2013 commit was correct in intent but commented out a single line instead of deleting the field, setter, import, and Spring
<property>. That left 12.5 years of undead code: Spring continued injecting aTemplateFacetreference into everyCalcBonusFacetinstance on every load, only for that reference to go nowhere. This PR removes the dead infrastructure.5. What we deliberately did NOT do
I initially considered adding a symmetric
calcActiveBonuses()call insideremoveTemplate(mirroringaddTemplate). After looking, rejected: every external caller already recalcs afterwards, so the added call would either be redundant work (a performance regression for the same dragon characters the 2013 commit was helping) or require a multi-file refactor to move the explicit calls from callers intoremoveTemplate. The latent footgun — "new code callingtemplateInputFacet.adddirectly without recalc'ing" — is real but no current call path exhibits it.Existing test coverage for this also wouldn't catch a missing recalc: the relevant tests (
PlayerCharacterTestin slowtest) exerciseaddTemplate → removeTemplatecycles but assertisNonAbilitystate, which goes throughnonAbilityFacet, not the bonus graph.6. What we DID add
A class-Javadoc note on
CalcBonusFacet(commit4b9ba73e32) capturing the convention so future contributors don't have to reverse-engineer the 2013 git history every time:Deferred (not in this PR)
AbilityFromClassChoiceSet.java:144// TODO This is a bug -> it was not properly gathering beforecomment; touching the dead store would mask the known bug.FactSetParser.unparsereturn nullon the error path (afteraddWriteMessage) matches the project-wide tokenunparseconvention; callers inTokenSupportexplicitly null-check. Returningnew String[0]would break parity with hundreds of other token unparse sites.SpotBugs delta
Tests
./gradlew compileJava— BUILD SUCCESSFUL./gradlew :test --tests "pcgen.cdom.*"— 2355 tests, 0 failures./gradlew :test --tests "plugin.lsttokens.*"— 9713 tests, 0 failuresThe lsttokens run is included because the changes touch facets and
applicationContext.xml.