Skip to content

Commit c06ab7a

Browse files
macmadeclaude
andcommitted
fix: Re-sync selected configuration on edit and honor the hash contract
Editing a configuration mutates it in place, but the selected configuration is persisted as a separate decoded snapshot, so after editing the selected row the extension kept formatting with the old URLs until the user re-selected it. Capture whether the edited row is the current selection before presenting the sheet and, on save, re-write the selected configuration with the edited value. Override hash to combine the same fields equality uses (name, swiftFormat, uncrustify), satisfying the NSObject equal-implies-equal-hash contract, and remove the dead isEqual(to:) forwarder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 4767dc9 commit c06ab7a

3 files changed

Lines changed: 53 additions & 5 deletions

File tree

Shared/Configuration.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@ public class Configuration: NSObject, Codable
5757
"\( super.description ): \( self.name )"
5858
}
5959

60-
public override func isEqual( to object: Any? ) -> Bool
61-
{
62-
self.isEqual( object )
63-
}
64-
6560
public override func isEqual( _ object: Any? ) -> Bool
6661
{
6762
guard let configuration = object as? Configuration
@@ -80,6 +75,17 @@ public class Configuration: NSObject, Codable
8075
return false
8176
}
8277

78+
public override var hash: Int
79+
{
80+
var hasher = Hasher()
81+
82+
hasher.combine( self.name )
83+
hasher.combine( self.swiftFormat )
84+
hasher.combine( self.uncrustify )
85+
86+
return hasher.finalize()
87+
}
88+
8389
public func download()
8490
{
8591
DispatchQueue.main.async

SharedTests/ConfigurationTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,36 @@ struct ConfigurationTests
104104
#expect( configuration.isEqual( "X" ) == false )
105105
#expect( configuration.isEqual( nil ) == false )
106106
}
107+
108+
@Test( "Equal configurations produce equal hashes" )
109+
func equalConfigurationsHaveEqualHashes()
110+
{
111+
let lhs = Configuration( name: "X", swiftFormat: URL( string: "https://a" ), uncrustify: URL( string: "https://b" ) )
112+
let rhs = Configuration( name: "X", swiftFormat: URL( string: "https://a" ), uncrustify: URL( string: "https://b" ) )
113+
114+
#expect( lhs == rhs )
115+
#expect( lhs.hash == rhs.hash )
116+
#expect( lhs.hashValue == rhs.hashValue )
117+
}
118+
119+
@Test( "Equal configurations coalesce in a Set" )
120+
func equalConfigurationsCoalesceInASet()
121+
{
122+
let lhs = Configuration( name: "X", swiftFormat: URL( string: "https://a" ), uncrustify: URL( string: "https://b" ) )
123+
let rhs = Configuration( name: "X", swiftFormat: URL( string: "https://a" ), uncrustify: URL( string: "https://b" ) )
124+
125+
let set: Set< Configuration > = [ lhs, rhs ]
126+
127+
#expect( set.count == 1 )
128+
}
129+
130+
@Test( "Equal configurations with nil URLs produce equal hashes" )
131+
func equalConfigurationsWithNilURLsHaveEqualHashes()
132+
{
133+
let lhs = Configuration( name: "Empty", swiftFormat: nil, uncrustify: nil )
134+
let rhs = Configuration( name: "Empty", swiftFormat: nil, uncrustify: nil )
135+
136+
#expect( lhs == rhs )
137+
#expect( lhs.hash == rhs.hash )
138+
}
107139
}

XcodeFormat/Classes/ConfigurationsWindowController.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ public class ConfigurationsWindowController: NSWindowController
127127
return
128128
}
129129

130+
// Capture whether this row is the persisted selection *before* the sheet
131+
// edits the object in place. selectedConfiguration is a separate decoded
132+
// snapshot, so without re-syncing it would keep the pre-edit URLs.
133+
let wasSelected = Preferences.shared.selectedConfiguration.map { configuration.isEqual( $0 ) } ?? false
134+
130135
controller.configuration = configuration
131136
self.configurationWindowController = controller
132137

@@ -135,6 +140,11 @@ public class ConfigurationsWindowController: NSWindowController
135140
if $0 == .OK
136141
{
137142
Preferences.shared.configurations = self.arrayController.content as? [ Configuration ] ?? []
143+
144+
if wasSelected
145+
{
146+
Preferences.shared.selectedConfiguration = configuration
147+
}
138148
}
139149
}
140150
}

0 commit comments

Comments
 (0)