@@ -217,6 +217,51 @@ final class CodedAtTests: XCTestCase {
217217 )
218218 }
219219
220+ func testWithNoPathAndDefaultValueOnOptionalType( ) throws {
221+ assertMacroExpansion (
222+ """
223+ @Codable
224+ @MemberInit
225+ struct SomeCodable {
226+ @Default( " some " )
227+ @CodedAt
228+ let value: String?
229+ }
230+ """ ,
231+ expandedSource:
232+ """
233+ struct SomeCodable {
234+ let value: String?
235+
236+ init(value: String? = " some " ) {
237+ self.value = value
238+ }
239+ }
240+
241+ extension SomeCodable: Decodable {
242+ init(from decoder: any Decoder) throws {
243+ do {
244+ self.value = try String?(from: decoder) ?? " some "
245+ } catch {
246+ self.value = " some "
247+ }
248+ }
249+ }
250+
251+ extension SomeCodable: Encodable {
252+ func encode(to encoder: any Encoder) throws {
253+ try self.value.encode(to: encoder)
254+ }
255+ }
256+
257+ extension SomeCodable {
258+ enum CodingKeys: String, CodingKey {
259+ }
260+ }
261+ """
262+ )
263+ }
264+
220265 func testWithNoPathWithHelperInstance( ) throws {
221266 assertMacroExpansion (
222267 """
@@ -304,6 +349,52 @@ final class CodedAtTests: XCTestCase {
304349 )
305350 }
306351
352+ func testWithNoPathWithHelperInstanceAndDefaultValueOnOptional( ) throws {
353+ assertMacroExpansion (
354+ """
355+ @Codable
356+ @MemberInit
357+ struct SomeCodable {
358+ @Default([ " some " ])
359+ @CodedBy(LossySequenceCoder<[String]>())
360+ @CodedAt
361+ let value: [String]?
362+ }
363+ """ ,
364+ expandedSource:
365+ """
366+ struct SomeCodable {
367+ let value: [String]?
368+
369+ init(value: [String]? = [ " some " ]) {
370+ self.value = value
371+ }
372+ }
373+
374+ extension SomeCodable: Decodable {
375+ init(from decoder: any Decoder) throws {
376+ do {
377+ self.value = try LossySequenceCoder<[String]>().decodeIfPresent(from: decoder) ?? [ " some " ]
378+ } catch {
379+ self.value = [ " some " ]
380+ }
381+ }
382+ }
383+
384+ extension SomeCodable: Encodable {
385+ func encode(to encoder: any Encoder) throws {
386+ try LossySequenceCoder<[String]>().encodeIfPresent(self.value, to: encoder)
387+ }
388+ }
389+
390+ extension SomeCodable {
391+ enum CodingKeys: String, CodingKey {
392+ }
393+ }
394+ """
395+ )
396+ }
397+
307398 func testWithSinglePath( ) throws {
308399 assertMacroExpansion (
309400 """
@@ -395,6 +486,54 @@ final class CodedAtTests: XCTestCase {
395486 )
396487 }
397488
489+ func testWithSinglePathAndDefaultValueOnOptionalType( ) throws {
490+ assertMacroExpansion (
491+ """
492+ @Codable
493+ @MemberInit
494+ struct SomeCodable {
495+ @Default( " some " )
496+ @CodedAt( " key " )
497+ let value: String?
498+ }
499+ """ ,
500+ expandedSource:
501+ """
502+ struct SomeCodable {
503+ let value: String?
504+
505+ init(value: String? = " some " ) {
506+ self.value = value
507+ }
508+ }
509+
510+ extension SomeCodable: Decodable {
511+ init(from decoder: any Decoder) throws {
512+ let container = try decoder.container(keyedBy: CodingKeys.self)
513+ do {
514+ self.value = try container.decodeIfPresent(String.self, forKey: CodingKeys.value) ?? " some "
515+ } catch {
516+ self.value = " some "
517+ }
518+ }
519+ }
520+
521+ extension SomeCodable: Encodable {
522+ func encode(to encoder: any Encoder) throws {
523+ var container = encoder.container(keyedBy: CodingKeys.self)
524+ try container.encodeIfPresent(self.value, forKey: CodingKeys.value)
525+ }
526+ }
527+
528+ extension SomeCodable {
529+ enum CodingKeys: String, CodingKey {
530+ case value = " key "
531+ }
532+ }
533+ """
534+ )
535+ }
536+
398537 func testWithSinglePathWithHelperInstance( ) throws {
399538 assertMacroExpansion (
400539 """
@@ -488,6 +627,55 @@ final class CodedAtTests: XCTestCase {
488627 )
489628 }
490629
630+ func testWithOnePathWithHelperInstanceAndDefaultValueOnOptional( ) throws {
631+ assertMacroExpansion (
632+ """
633+ @Codable
634+ @MemberInit
635+ struct SomeCodable {
636+ @Default([ " some " ])
637+ @CodedBy(LossySequenceCoder<[String]>())
638+ @CodedAt( " key " )
639+ let value: [String]?
640+ }
641+ """ ,
642+ expandedSource:
643+ """
644+ struct SomeCodable {
645+ let value: [String]?
646+
647+ init(value: [String]? = [ " some " ]) {
648+ self.value = value
649+ }
650+ }
651+
652+ extension SomeCodable: Decodable {
653+ init(from decoder: any Decoder) throws {
654+ let container = try decoder.container(keyedBy: CodingKeys.self)
655+ do {
656+ self.value = try LossySequenceCoder<[String]>().decodeIfPresent(from: container, forKey: CodingKeys.value) ?? [ " some " ]
657+ } catch {
658+ self.value = [ " some " ]
659+ }
660+ }
661+ }
662+
663+ extension SomeCodable: Encodable {
664+ func encode(to encoder: any Encoder) throws {
665+ var container = encoder.container(keyedBy: CodingKeys.self)
666+ try LossySequenceCoder<[String]>().encodeIfPresent(self.value, to: &container, atKey: CodingKeys.value)
667+ }
668+ }
669+
670+ extension SomeCodable {
671+ enum CodingKeys: String, CodingKey {
672+ case value = " key "
673+ }
674+ }
675+ """
676+ )
677+ }
678+
491679 func testWithNestedPath( ) throws {
492680 assertMacroExpansion (
493681 """
@@ -591,6 +779,60 @@ final class CodedAtTests: XCTestCase {
591779 )
592780 }
593781
782+ func testWithNestedPathAndDefaultValueOnOptionalType( ) throws {
783+ assertMacroExpansion (
784+ """
785+ @Codable
786+ @MemberInit
787+ struct SomeCodable {
788+ @Default( " some " )
789+ @CodedAt( " deeply " , " nested " , " key " )
790+ let value: String?
791+ }
792+ """ ,
793+ expandedSource:
794+ """
795+ struct SomeCodable {
796+ let value: String?
797+
798+ init(value: String? = " some " ) {
799+ self.value = value
800+ }
801+ }
802+
803+ extension SomeCodable: Decodable {
804+ init(from decoder: any Decoder) throws {
805+ let container = try decoder.container(keyedBy: CodingKeys.self)
806+ let deeply_container = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.deeply)
807+ let nested_deeply_container = try deeply_container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.nested)
808+ do {
809+ self.value = try nested_deeply_container.decodeIfPresent(String.self, forKey: CodingKeys.value) ?? " some "
810+ } catch {
811+ self.value = " some "
812+ }
813+ }
814+ }
815+
816+ extension SomeCodable: Encodable {
817+ func encode(to encoder: any Encoder) throws {
818+ var container = encoder.container(keyedBy: CodingKeys.self)
819+ var deeply_container = container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.deeply)
820+ var nested_deeply_container = deeply_container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.nested)
821+ try nested_deeply_container.encodeIfPresent(self.value, forKey: CodingKeys.value)
822+ }
823+ }
824+
825+ extension SomeCodable {
826+ enum CodingKeys: String, CodingKey {
827+ case value = " key "
828+ case deeply = " deeply "
829+ case nested = " nested "
830+ }
831+ }
832+ """
833+ )
834+ }
835+
594836 func testWithNestedPathWithHelperInstance( ) throws {
595837 assertMacroExpansion (
596838 """
@@ -695,5 +937,61 @@ final class CodedAtTests: XCTestCase {
695937 """
696938 )
697939 }
940+
941+ func testWithNestedPathWithHelperInstanceAndDefaultValueOnOptional( ) throws
942+ {
943+ assertMacroExpansion (
944+ """
945+ @Codable
946+ @MemberInit
947+ struct SomeCodable {
948+ @Default([ " some " ])
949+ @CodedBy(LossySequenceCoder<[String]>())
950+ @CodedAt( " deeply " , " nested " , " key " )
951+ let value: [String]?
952+ }
953+ """ ,
954+ expandedSource:
955+ """
956+ struct SomeCodable {
957+ let value: [String]?
958+
959+ init(value: [String]? = [ " some " ]) {
960+ self.value = value
961+ }
962+ }
963+
964+ extension SomeCodable: Decodable {
965+ init(from decoder: any Decoder) throws {
966+ let container = try decoder.container(keyedBy: CodingKeys.self)
967+ let deeply_container = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.deeply)
968+ let nested_deeply_container = try deeply_container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.nested)
969+ do {
970+ self.value = try LossySequenceCoder<[String]>().decodeIfPresent(from: nested_deeply_container, forKey: CodingKeys.value) ?? [ " some " ]
971+ } catch {
972+ self.value = [ " some " ]
973+ }
974+ }
975+ }
976+
977+ extension SomeCodable: Encodable {
978+ func encode(to encoder: any Encoder) throws {
979+ var container = encoder.container(keyedBy: CodingKeys.self)
980+ var deeply_container = container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.deeply)
981+ var nested_deeply_container = deeply_container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.nested)
982+ try LossySequenceCoder<[String]>().encodeIfPresent(self.value, to: &nested_deeply_container, atKey: CodingKeys.value)
983+ }
984+ }
985+
986+ extension SomeCodable {
987+ enum CodingKeys: String, CodingKey {
988+ case value = " key "
989+ case deeply = " deeply "
990+ case nested = " nested "
991+ }
992+ }
993+ """
994+ )
995+ }
698996}
699997#endif
0 commit comments