Extract IUndoRenameLogic narrow port; inject it into UndoManager in place of IRenameLogic (ADR-0005 Phase 3)#3356
Merged
Merged
Conversation
…lace of IRenameLogic (ADR-0005 Phase 3) Mirrors #3355 (IUndoPluginNotifier). UndoManager injected the full, MEF/WinForms-entangled IRenameLogic but called only three of its ~12 methods (HandleRename, GetChangesForRenamedVariable, ApplyVariableRenameChanges), all with headless GumDataTypes/ToolsUtilities parameters. This extracts those three calls into a narrow port, IUndoRenameLogic, in the headless Gum.Presentation assembly, and injects that port into UndoManager in place of IRenameLogic. The three methods' closure pulled five small data types out of the tool's Gum/Logic/RenameLogic.cs (NameChangeAction + SideOfEquals enums; VariableChange / VariableReferenceChange / VariableChangeResponse) which are relocated to Tools/Gum.Presentation/Logic/RenameChangeTypes.cs, keeping the Gum.Logic namespace so the ~20 tool-side consumers compile unchanged. RenameLogic's signatures matched exactly, so ': IRenameLogic, IUndoRenameLogic' was all that was needed (no adapter). DI registers RenameLogic as its own singleton and resolves both interfaces to it, so rename calls fire as before. This is the last shell-only ctor dependency UndoManager held; with it ported, all of UndoManager's ctor deps are now headless, a prerequisite for relocating the class itself headless in a later PR. This PR does NOT move UndoManager. Tests: the two existing rename-delegation pinning tests now mock Mock<IUndoRenameLogic>. Added PerformUndo_OnElementRename_ShouldDelegateToRenameLogicHandleRename to pin the third call (HandleRename) - red-first verified (disabling the seam produced 'No invocations performed'). Full GumToolUnitTests suite green: 1000 passed, 0 failed, 4 pre-existing skips. AllPluginsCompositionTests confirms plugins still compose via MEF. Gum.Presentation builds standalone (zero WPF/WinForms leak). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vchelaru
added a commit
that referenced
this pull request
Jun 25, 2026
…esentation (ADR-0005 Phase 3) (#3357) First concrete logic class (not just a contract) to cross the headless boundary, unblocked by #3355 (IUndoPluginNotifier) and #3356 (IUndoRenameLogic), which drained UndoManager's last two tool-coupled ctor deps. All 6 ctor deps are now headless interfaces and the body references no tool-only types. - git mv Gum/Undo/UndoManager.cs and AfterUndoMessage.cs -> Tools/Gum.Presentation/Undo/. Namespace stays Gum.Undo, so Builder.cs DI and all consumers (incl. PluginManager's AfterUndoMessage handler) compile unchanged. - Drop now-stale usings Gum.Managers and Gum.Wireframe. - Localize the tool-only StateSave.SetFrom extension as a private UndoManager.SetStateContentsFrom helper (UndoManager was its only caller in the repo); remove the orphan from StateSaveExtensionMethodsGumTool. FixEnumerations is now unconditional, matching prior tool behavior (the extension guarded it with #if GUM, and GUM is defined in the tool build). - Delete the dead GetWhatToApplyTo method and its only-consumer UndoObject.cs. - Grant Gum.Presentation InternalsVisibleTo GumToolUnitTests so UndoManagerTests keeps reaching the internal UndoLocks; Gum.csproj already granted this via AssemblyInfo, so the grant moves with the class. Behavior-preserving. Verified: Gum.Presentation compiles standalone (0 errors, no WPF/WinForms leak); GumFull.sln builds (0 errors); GumToolUnitTests 1000 passed / 0 failed / 4 skipped. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vchelaru
added a commit
that referenced
this pull request
Jun 25, 2026
…s Gum.Presentation (ADR-0005 Phase 3) (#3360) git mv Gum/Logic/IReferenceFinder.cs -> Tools/Gum.Presentation/Logic/IReferenceFinder.cs, and extract the reference-result types it returns (ElementReferences, InstanceReferences, StateReferences, BehaviorReferences, CategoryReferences) out of the WPF-entangled Gum/Logic/RenameLogic.cs into a new headless file Tools/Gum.Presentation/Logic/ReferenceTypes.cs (mirroring the RenameChangeTypes.cs precedent from #3356). All five types — not the three named in the original scoping — had to move: IReferenceFinder also returns StateReferences and CategoryReferences, so the port could not compile in Gum.Presentation without them. VariableChangeResponse, the sixth return type, was already relocated in #3356. The full dependency closure is framework-neutral (GumDataTypes + the already-relocated VariableChange/VariableReferenceChange), so nothing tool-only crossed the boundary. Namespace stays Gum.Logic for every moved type, so tool-side consumers (RenameLogic, the concrete ReferenceFinder, DeleteLogic, EditCommands) compile unchanged. The concrete impl (Gum/Logic/ReferenceFinder.cs, DI-registered in Builder.cs) stays in the shell. Behavior-preserving: Gum.Presentation compiles standalone (no WPF leak), GumFull.sln builds clean, and 982 GumToolUnitTests pass. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 25, 2026
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.
What
Mirrors #3355 (
IUndoPluginNotifier), this time forIRenameLogic— the last shell-only ctor dependencyUndoManagerheld before it can be relocated headless (ADR-0005 Phase 3).UndoManagerinjected the full, MEF/WinForms-entangledIRenameLogicbut called only three of its ~12 methods —HandleRename,GetChangesForRenamedVariable,ApplyVariableRenameChanges— all with headlessGumDataTypes/ToolsUtilitiesparameters. This PR extracts those three calls into a narrow port,IUndoRenameLogic, in the headlessGum.Presentationassembly, and injects that port intoUndoManagerin place ofIRenameLogic.How
Tools/Gum.Presentation/Undo/IUndoRenameLogic.cs(namespaceGum.Undo, alongsideIUndoManager/IUndoPluginNotifier) — exactly the 3 members.Gum/Logic/RenameLogic.csintoTools/Gum.Presentation/Logic/RenameChangeTypes.cs— the 3 methods' closure pulled them in:NameChangeAction+SideOfEqualsenums, andVariableChange/VariableReferenceChange/VariableChangeResponse. All are framework-neutral (GumDataTypes/ToolsUtilities only). They keep theGum.Logicnamespace, so the ~20 tool-side consumers compile unchanged (the file physically moves assemblies; the namespace travels with the types). Confirmed via an assembly-graph sweep that no consumer compiles intoGumCommon/Gum.ProjectServices(which would have forced them lower) — every consumer is in the toolGum.dllor its test assembly.RenameLogicimplements it — its existing method signatures matched the port exactly, so: IRenameLogic, IUndoRenameLogicwas all that was needed — no shim/adapter.Builder.cs) registersRenameLogicas its own singleton and resolves bothIRenameLogicandIUndoRenameLogicto it, so the rename calls fire against the same instance as before (mirrors thePluginManager3-line pattern).UndoManagerfield/ctor paramIRenameLogic _renameLogic→IUndoRenameLogic _renameLogic; the 3 call sites are unchanged (field name kept).Behavior-preserving
The three rename calls route through the narrow port unchanged. This is the canonical refactoring-direction "narrow port over an entangled dependency" pattern. With it landed, all of
UndoManager's ctor deps are now headless (ISelectedState,IUndoRenameLogic,IGuiCommands,IFileCommands,IMessenger,IUndoPluginNotifier) — and its body references no tool-only types — so the class itself can be relocated toGum.Presentationin a follow-up. This PR does NOT moveUndoManager. File-disjoint from #3355.Tests
Mock<IUndoRenameLogic>(coveringGetChangesForRenamedVariable/ApplyVariableRenameChanges).PerformUndo_OnElementRename_ShouldDelegateToRenameLogicHandleRenameto pin the third call (HandleRename) — red-first verified (disabling the seam produced "No invocations performed").GumToolUnitTestssuite green: 1000 passed, 0 failed, 4 pre-existing skips.AllPluginsCompositionTestsconfirms plugins still compose via MEF.Gum.Presentationbuilds standalone (zero WPF/WinForms leak);GumFull.slnbuilds with 0 errors.Manual test: not needed — behavior-preserving narrow-port swap + type relocation, proven by the compiler (
GumFull.sln+ standaloneGum.Presentation), the full unit suite, and the red-first pinning check.🤖 Generated with Claude Code