@@ -307,7 +307,7 @@ private func expandAccessorMacroWithExistingAccessors(
307
307
return nil
308
308
}
309
309
310
- // Separate the accessor from any existing accessors by two spaces
310
+ // Separate the accessor from any existing accessors by an empty line
311
311
let indentedSource = " \n " + expanded. indented ( by: attachedTo. indentationOfFirstLine + indentationWidth)
312
312
return " \( raw: indentedSource) "
313
313
}
@@ -702,13 +702,27 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
702
702
context. addDiagnostics ( from: MacroApplicationError . accessorMacroOnVariableWithMultipleBindings, node: node)
703
703
return DeclSyntax ( node)
704
704
}
705
- node. bindings [ node. bindings. startIndex] . accessorBlock = expandAccessors ( of: node, existingAccessors: binding. accessorBlock)
705
+
706
+
707
+ let expansion = expandAccessors ( of: node, existingAccessors: binding. accessorBlock)
708
+ if expansion. accessors != binding. accessorBlock {
709
+ if binding. initializer != nil , expansion. expandsGetSet {
710
+ // The accessor block will have a leading space, but there will already be a
711
+ // space between the variable and the to-be-removed initializer. Remove the
712
+ // leading trivia on the accessor block so we don't double up.
713
+ node. bindings [ node. bindings. startIndex] . accessorBlock = expansion. accessors? . with ( \. leadingTrivia, [ ] )
714
+ node. bindings [ node. bindings. startIndex] . initializer = nil
715
+ } else {
716
+ node. bindings [ node. bindings. startIndex] . accessorBlock = expansion. accessors
717
+ }
718
+ }
719
+
706
720
return DeclSyntax ( node)
707
721
}
708
722
709
723
override func visit( _ node: SubscriptDeclSyntax ) -> DeclSyntax {
710
724
var node = super. visit ( node) . cast ( SubscriptDeclSyntax . self)
711
- node. accessorBlock = expandAccessors ( of: node, existingAccessors: node. accessorBlock)
725
+ node. accessorBlock = expandAccessors ( of: node, existingAccessors: node. accessorBlock) . accessors
712
726
return DeclSyntax ( node)
713
727
}
714
728
}
@@ -869,14 +883,21 @@ extension MacroApplication {
869
883
}
870
884
}
871
885
872
- /// Expand all 'accessor' macros attached to `storage` and return the `storage`
873
- /// node.
886
+ /// Expand all 'accessor' macros attached to `storage`.
874
887
///
875
- /// - Returns: The storage node with all macro-synthesized accessors applied.
876
- private func expandAccessors( of storage: some DeclSyntaxProtocol , existingAccessors: AccessorBlockSyntax ? ) -> AccessorBlockSyntax ? {
888
+ /// - Returns: The final accessors block that includes both the existing
889
+ /// and expanded accessors, as well as whether any `get`/`set` were
890
+ /// expanded (in which case any initializer on `storage` should be
891
+ /// removed).
892
+ private func expandAccessors( of storage: some DeclSyntaxProtocol , existingAccessors: AccessorBlockSyntax ? ) -> ( accessors: AccessorBlockSyntax ? , expandsGetSet: Bool ) {
877
893
let accessorMacros = macroAttributes ( attachedTo: DeclSyntax ( storage) , ofType: AccessorMacro . Type. self)
878
894
879
895
var newAccessorsBlock = existingAccessors
896
+ var expandsGetSet = false
897
+ func checkExpansions( _ accessors: AccessorDeclListSyntax ? ) {
898
+ guard let accessors else { return }
899
+ expandsGetSet = expandsGetSet || accessors. contains ( where: \. isGetOrSet)
900
+ }
880
901
881
902
for macro in accessorMacros {
882
903
do {
@@ -894,6 +915,8 @@ extension MacroApplication {
894
915
in: context,
895
916
indentationWidth: indentationWidth
896
917
) {
918
+ checkExpansions ( newAccessors)
919
+
897
920
// If existingAccessors is not `nil`, then we also set
898
921
// `newAccessorBlock` above to a a non-nil value, so
899
922
// `newAccessorsBlock` also isn’t `nil`.
@@ -902,31 +925,33 @@ extension MacroApplication {
902
925
indentationWidth: self . indentationWidth
903
926
)
904
927
}
905
- } else {
906
- let newAccessors = try expandAccessorMacroWithoutExistingAccessors (
907
- definition : macro. definition ,
908
- attributeNode : macro . attributeNode ,
909
- attachedTo : DeclSyntax ( storage ) ,
910
- in : context ,
911
- indentationWidth : indentationWidth
912
- )
913
- if newAccessorsBlock == nil {
914
- newAccessorsBlock = newAccessors
915
- } else if let newAccessors = newAccessors {
916
- guard case . accessors ( let accessorList) = newAccessors . accessors else {
917
- throw MacroApplicationError . malformedAccessor
918
- }
919
- newAccessorsBlock = newAccessorsBlock! . addingAccessors (
928
+ } else if let newAccessors = try expandAccessorMacroWithoutExistingAccessors (
929
+ definition : macro . definition ,
930
+ attributeNode : macro. attributeNode ,
931
+ attachedTo : DeclSyntax ( storage ) ,
932
+ in : context ,
933
+ indentationWidth : indentationWidth
934
+ ) {
935
+ guard case . accessors ( let accessorList ) = newAccessors . accessors else {
936
+ throw MacroApplicationError . malformedAccessor
937
+ }
938
+
939
+ checkExpansions ( accessorList)
940
+
941
+ if let oldBlock = newAccessorsBlock {
942
+ newAccessorsBlock = oldBlock . addingAccessors (
920
943
from: accessorList,
921
944
indentationWidth: self . indentationWidth
922
945
)
946
+ } else {
947
+ newAccessorsBlock = newAccessors
923
948
}
924
949
}
925
950
} catch {
926
951
context. addDiagnostics ( from: error, node: macro. attributeNode)
927
952
}
928
953
}
929
- return newAccessorsBlock
954
+ return ( newAccessorsBlock, expandsGetSet )
930
955
}
931
956
}
932
957
@@ -1130,3 +1155,9 @@ private extension AttributeSyntax {
1130
1155
return ( detach ( in: context, foldingWith: operatorTable) as Syntax ) . cast ( Self . self)
1131
1156
}
1132
1157
}
1158
+
1159
+ private extension AccessorDeclSyntax {
1160
+ var isGetOrSet : Bool {
1161
+ return accessorSpecifier. tokenKind == . keyword( . get) || accessorSpecifier. tokenKind == . keyword( . set)
1162
+ }
1163
+ }
0 commit comments