Repository navigation
Detect inherited AT and AW members, plus cross-file AT conflicts - #17
Conversation
|
Follow-up: access wideners now get the same inherited-member detection, so the two validators no longer disagree about a rule they both have. I verified the semantics against Fabric's own implementation rather than assuming they matched. accessWidener.getMethodAccess(new EntryTriple(className, name, descriptor))
...
Access getMethodAccess(EntryTriple entryTriple) {
return methodAccess.getOrDefault(entryTriple, MethodAccess.DEFAULT);So an AW entry naming a subclass for an inherited member widens nothing — identical to ATs, and identically silent. The hierarchy walk therefore moved to One detail worth noting: the AW parser dot-normalizes class names, so the message renders the declarer in whichever notation the entry used (no 570 tests passing. |
Finishes the access transformer work from #12. The bytecode switch in #16 fixed the record false positives and made these remaining quirks solvable. With this, AT support covers everything the issue raised, and the same inherited-member handling applies to Fabric access wideners.
Inherited members
An AT only transforms the class it names. Point one at a member the class merely inherits and it's silently inert — the build passes, the game loads, the member stays inaccessible. The validator previously made this worse by suggesting a typo fix for a member that exists perfectly well one class up.
It now resolves the full ancestor closure and reports the class that actually declares the member, with a corrected directive you can paste over the broken line:
superName+ interfaces and runs in rounds, since a parent is only discoverable from its child's class file.java.lang.*, library types) are skipped, not reported missing.tick(I)Vwhen the AT asks fortick()Vis reported as an inheritance problem rather than a bad descriptor.<init>would be wrong advice.Access wideners
Fabric AWs have identical semantics.
AccessWidenerClassVisitorlooks upEntryTriple(className, name, descriptor)against the class it's visiting through a plainHashMap.getOrDefault, with no hierarchy resolution. An AW naming a subclass for an inherited member widens nothing.The hierarchy walk lives in
src/utils/bytecode-hierarchy.tsand both validators share it, so they can't drift on a rule they both have. Only the corrected-directive rendering differs, since the grammars do.Access widener class-name notation
The AW parser normalized class names to dots (
parts[2].replace(/\//g, '.')), so every directive and suggestion came out dotted. Access wideners are slash-only — Fabric's reader errors with "Class-names must be specified as a/b/C, not a.b.C" — meaning a pasted suggestion would break the build.The parser now preserves the token as written. Lookups already went through
toInternalName(), which normalizes either form.Cross-file conflicts
Mods routinely ship more than one AT and the loader applies them together, so a conflict spanning two files fails the Forge build exactly like one inside a single file.
validate_access_transformertakes an optionalextraFiles.Siblings aren't validated against bytecode — validate each on its own call for that. They join the union only for the checks where a second file changes the answer:
Findings are restricted to those involving the file being validated, so checking
a.cfgnever re-reports an argument that exists purely betweenb.cfgandc.cfg. A path that doesn't resolve comes back asextraFilesNotFoundrather than being dropped, which would read as "no conflicts found".CLI array flags
extraFilesis the first array param anyone would realistically type by hand, and the CLI only took JSON (--extraFiles '["a.cfg","b.cfg"]'), which is miserable to quote through cmd.exe or PowerShell. Now--extraFiles a.cfg,b.cfgand repeated--extraFiles a.cfg --extraFiles b.cfgboth work. JSON still parses; non-array flags keep last-wins.Verified against real Minecraft bytecode
AnyOfCondition terms→CompositeLootItemCondition,LivingEntity getType()→Entityon both the AT and AW side. Locally-declared members stay clean.Tests
575 passing.
access-transformer-inheritance.test.ts(18): superclass chain, multi-level walks, interface default methods, overrides, descriptor-mismatch precedence, unresolvable parents, cyclic hierarchies, constructor exclusion, and the cross-file conflict/duplicate/restriction/record-suppression matrix. Two run against the real committed stub JAR.validate_access_wideneroutput, covering the rendered payload rather than the envelope shape — directive, message and suggestion as they reach the caller.extraFilescoverage at the tool layer, and CLI array-flag tests.